本文是基于小蔗平日的开发习惯所写的构建流程速览,供君参阅。
技术栈:SvelteKit、TailwindCSS、[ DaisyUI / Carbon Design System / ShadcnUI ]
以下为开发环境及框架准备流程。
参考文档:[ Creating a project ]
构建 SvelteKit
npm create svelte@latest gxz-app
项目选择
create-svelte version 3.0.1
Welcome to SvelteKit!
✔ Which Svelte app template? › Skeleton project
✔ Add type checking with TypeScript? › Yes, using TypeScript syntax
✔ Add ESLint for code linting? … Yes
✔ Add Prettier for code formatting? … Yes
✔ Add Playwright for browser testing? … No
✔ Add Vitest for unit testing? … No
下一步
cd gxz-app
npm install
npm run dev -- --open
现在你可以直接使用 `npx svelte-add@latest tailwindcss` 为 SvelteKit 安装 TailwindCSS,如果要从国内镜像下载,请使用
$ alias cnpx='NPM_CONFIG_REGISTRY=https://registry.npmmirror.com npx'
$ cnpx svelte-add@latest tailwindcss
参考自 https://segmentfault.com/q/1010000021786171
参考文档:[ Install Tailwind CSS with SvelteKit ]
cnpm install -D tailwindcss postcss autoprefixer
npx tailwindcss init tailwind.config.cjs -p
文件 svelte.config.js
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/kit/vite';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter()
},
preprocess: vitePreprocess()
};
export default config;
修改文件 tailwind.config.cjs
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {}
},
plugins: []
};
在 app.css 引入
@tailwind base;
@tailwind components;
@tailwind utilities;
通过 SvelteKit 的 filesystem-based router 创建 /+layout.svelte 文件引入 app.css
<script>
import '../app.css';
</script>
<slot />
建议安装排版插件 @tailwindcss/typography ;
建议类名排序插件 @tailwindlabs/prettier-plugin-tailwindcss,以及为什么推荐类名排序。
# 排版
cnpm install -D @tailwindcss/typography
# 类名排序
cnpm install -D prettier prettier-plugin-tailwindcss
安装排版插件后在 tailwind.config.cjs 的 plugins 对象处引入即可;类名排序插件则需在 prettier.config.js 的 plugins 对象引入。
// tailwind.config.cjs
plugins: [require('@tailwindcss/typography')],
// prettier.config.js
module.exports = {
plugins: [require('prettier-plugin-tailwindcss')],
}
参考文档:[ Install daisyUI as a Tailwind CSS plugin ]
cnpm i -D daisyui
修改文件 tailwind.config.cjs 的 plugins 对象,同时由于 DaisyUI 对 tailiwind 增加了一些风格样式,所以需要放在其之后
module.exports = {
//...
plugins: [require('@tailwindcss/typography'), require('daisyui')],
daisyui: {
themes: ['dark', 'light']
},
darkMode: ['class', '[data-theme="dark"]'],
}
参考文档:[ Developing ] [ Frameworks ]
# 组件
cnpm i -D carbon-components-svelte
# 图标
cnpm i -D carbon-icons-svelte
# 图表
cnpm i -D @carbon/charts-svelte d3
# 预处理,编译优化
cnpm i -D carbon-preprocess-svelte
修改 /+layout.svelte 文件,注意这里导入了所有主题 (theme),便于做深浅色主题切换
<script lang='ts'>
import '../app.css';
import 'carbon-components-svelte/css/all.css';
</script>
<slot />
关于 Carbon Components 的动态主题可参见 [GitHub] Dynamic theming,同时为了完成 Tailwind 的深浅色主题适配,还需修改 tailwind.config.cjs 的 darkMode 对象值
module.exports = {
//...
plugins: [require('@tailwindcss/typography')],
darkMode: ['class', '[theme="g80"]', '[theme="g90"]', '[theme="g100"]'],
}
其余配置详见 Frameworks 文档中各个项目的的 GitHub 地址。
shadcn-svelte 是 shadcn/ui 非官方的 Svelte 版本,它不像任何其他 UI 库,shadcn-svelte 是一个可复用组件的集合。你可以通过复制粘贴,或者使用 CLI 将其添加到应用程序中,其中风格样式与代码实现是分离的,这种设计不失为巧妙。
shadcn-svelte 依赖 TailwindCSS,这里假设你已经安装好 Tailwind。
设置 svelte.config.js 路径别名
const config = {
// ... other config
kit: {
// ... other config
alias: {
"@/*": "./path/to/lib/*",
},
},
};
初始化 CLI
npx shadcn-svelte@latest init
配置 components.json
Would you like to use TypeScript (recommended)? › Yes
Which style would you like to use? › Default
Which color would you like to use as base color? › Slate
Where is your global CSS file? › src/app.pcss
Where is your tailwind.config.[cjs|js|ts] located? › tailwind.config.js
Configure the import alias for components: › $lib/components
Configure the import alias for utils: › $lib/utils
安装组件
npx shadcn-svelte@latest add button
# 一些常用组件
npx shadcn-svelte@latest add avatar badge button card checkbox command dialog dropdown-menu input label pagination popover radio-group select separator skeleton textarea
使用组件
<script lang="ts">
import { Button } from "$lib/components/ui/button";
</script>
<Button>Click me</Button>
安装 mode-watcher
npm install mode-watcher
修改文件 src/routes/+layout.svelte
<script lang="ts">
import { ModeWatcher } from "mode-watcher";
</script>
<ModeWatcher />
<slot />
调用 mode-watcher 方法
<script lang='ts'>
import { IconSun, IconMoonStars } from '@tabler/icons-svelte';
import { resetMode, setMode } from "mode-watcher";
import { Button } from "$lib/components/ui/button/index.js";
import * as DropdownMenu from "$lib/components/ui/dropdown-menu/index.js";
</script>
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild let:builder>
<Button builders={[builder]} variant="ghost" size="icon">
<IconSun class="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<IconMoonStars class="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span class="sr-only">切换主题</span>
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content align="end">
<DropdownMenu.Item on:click={() => setMode("light")}>浅色主题</DropdownMenu.Item>
<DropdownMenu.Item on:click={() => setMode("dark")}>深色主题</DropdownMenu.Item>
<DropdownMenu.Item on:click={() => resetMode()}>跟随系统</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
以下为构建及部署流程。
参考文档:[ Adapters ] [ Static site generation ]
使用静态适配器
cnpm i -D @sveltejs/adapter-static
修改 svelte.config.js 文件
//import adapter from '@sveltejs/adapter-auto';
import adapter from '@sveltejs/adapter-static';
import { vitePreprocess } from '@sveltejs/kit/vite';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors
preprocess: vitePreprocess(),
kit: {
adapter: adapter({
// default options are shown. On some platforms
// these options are set automatically — see below
pages: 'build',
assets: 'build',
fallback: null,
precompress: false,
strict: true
})
}
};
export default config;
add the prerender option to root layout (+layout.ts)
// This can be false if you're using a fallback (i.e. SPA mode)
export const prerender = true;
export const ssr = false;
export const trailingSlash = 'always';
构建
npm run build
服务器:debian
curl https://get.acme.sh | sh -s email=re@gxzv.com
alias acme.sh=~/.acme.sh/acme.sh
# Please install socat tools first.
apt install socat
获取证书
// standalone
acme.sh --issue -d my.unique.quest --standalone
// dns
acme.sh --issue --dns -d my.unique.quest --yes-I-know-dns-manual-mode-enough-go-ahead-please
acme.sh --renew -d my.unique.quest --yes-I-know-dns-manual-mode-enough-go-ahead-please
安装证书
acme.sh --install-cert -d my.unique.quest --fullchain-file /etc/ssl/my.unique.quest.crt --key-file /etc/ssl/my.unique.quest.key --ecc
同时这一套技术栈也可用于 Electron 应用开发,类似框架可参考 [ Vite Electron Builder Boilerplate ]
配置文件
{
"name": "distributed-balanced-load",
"description": "Water-cooled distributed load balancing upper computer program.",
"version": "0.1.0",
"private": true,
"author": {
"email": "hi@gxzv.com",
"name": "Ganxiaozhe",
"url": "https://gxzv.com"
},
"main": "packages/main/dist/index.cjs",
"scripts": {
"build": "npm run build:main && npm run build:preload && npm run build:renderer",
"build:main": "cd ./packages/main && vite build",
"build:preload": "cd ./packages/preload && vite build",
"build:renderer": "cd ./packages/renderer && vite build",
"compile": "cross-env MODE=production npm run build && electron-builder build --config .electron-builder.config.js --dir --config.asar=false",
"builder": "cross-env MODE=production npm run build && electron-builder build --config .electron-builder.config.js -w",
"test": "npm run test:main && npm run test:preload && npm run test:renderer && npm run test:e2e",
"test:e2e": "npm run build && vitest run",
"test:main": "vitest run -r packages/main --passWithNoTests",
"test:preload": "vitest run -r packages/preload --passWithNoTests",
"test:renderer": "vitest run -r packages/renderer --passWithNoTests",
"watch": "node scripts/watch.mjs",
"lint": "eslint . --ext js,mjs,cjs,ts,mts,cts",
"typecheck:main": "tsc --noEmit -p packages/main/tsconfig.json",
"typecheck:preload": "tsc --noEmit -p packages/preload/tsconfig.json",
"typecheck:renderer": "svelte-check --tsconfig packages/renderer/tsconfig.json",
"typecheck": "npm run typecheck:main && npm run typecheck:preload && npm run typecheck:renderer",
"postinstall": "cross-env ELECTRON_RUN_AS_NODE=1 electron scripts/update-electron-vendors.mjs",
"format": "npx prettier --write \"**/*.{js,mjs,cjs,ts,mts,cts,json}\"",
"format:check": "npx prettier --check \"**/*.{js,mjs,cjs,ts,mts,cts,json}\""
},
"devDependencies": {
"@carbon/charts-svelte": "^1.6.4",
"@sveltejs/vite-plugin-svelte": "^2.0.2",
"@tsconfig/svelte": "^3.0.0",
"@types/node": "18.13.0",
"@typescript-eslint/eslint-plugin": "5.51.0",
"@typescript-eslint/parser": "^5.46.0",
"autoprefixer": "^10.4.13",
"carbon-components-svelte": "^0.72.2",
"carbon-icons-svelte": "^11.4.0",
"cross-env": "7.0.3",
"d3": "^7.8.2",
"daisyui": "^2.50.0",
"driver.js": "^0.9.8",
"electron": "23.0.0",
"electron-builder": "23.6.0",
"eslint": "8.33.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-html": "^7.1.0",
"eslint-plugin-markdown": "^3.0.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-svelte3": "^4.0.0",
"happy-dom": "8.2.6",
"nano-staged": "0.8.0",
"playwright": "1.30.0",
"postcss": "^8.4.19",
"prettier": "2.8.1",
"prettier-plugin-svelte": "^2.9.0",
"simple-git-hooks": "2.8.1",
"svelte": "^3.55.1",
"svelte-check": "^3.0.3",
"svelte-dnd-action": "^0.9.22",
"svelte-preprocess": "^4.10.7",
"tailwindcss": "^3.2.6",
"tslib": "^2.4.1",
"typescript": "4.9.5",
"unplugin-auto-expose": "0.0.4",
"vite": "4.1.1",
"vitest": "0.28.4"
},
"dependencies": {
"electron-updater": "5.3.0",
"serialport": "^10.5.0"
},
"prettier": {
"singleQuote": true,
"svelteStrictMode": true
}
}
至此。