开发环境: node >=18,npm >=8.10.2,vue <= 3.2.31
安装项目
npx degit dcloudio/uni-preset-vue#vite-ts vue3-uniapp
1、引入样式规范
npm add -D eslint eslint-config-airbnb-base eslint-config-prettier eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint-plugin-vue @typescript-eslint/eslint-plugin @typescript-eslint/parser vue-global-api
-
.editorconfig
# .editorconfig 文件 root = true [*] # 表示所有文件适用 charset = utf-8 # 设置文件字符集为 utf-8 indent_style = space # 缩进风格(tab | space) indent_size = 2 # 缩进大小 end_of_line = lf # 控制换行类型(lf | cr | crlf) trim_trailing_whitespace = true # 去除行首的任意空白字符 insert_final_newline = true # 始终在文件末尾插入一个新行 [*.md] # 表示仅 md 文件适用以下规则 max_line_length = off # 关闭最大行长度限制 trim_trailing_whitespace = false # 关闭末尾空格修剪
- .prettierrc.cjs
// @see https://prettier.io/docs/en/options module.exports = { singleQuote: true, printWidth: 100, tabWidth: 2, useTabs: false, semi: false, trailingComma: 'all', endOfLine: 'auto', }
- .eslintrc.cjs
// .eslintrc.cjs 文件 module.exports = { env: { browser: true, es2021: true, node: true, }, extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:vue/vue3-essential', // eslint-plugin-import 插件, @see https://www.npmjs.com/package/eslint-plugin-import 'plugin:import/recommended', // eslint-config-airbnb-base 插件, tips: 本插件也可以替换成 eslint-config-standard 'airbnb-base', // 1. 接入 prettier 的规则 'prettier', 'plugin:prettier/recommended', 'vue-global-api', ], overrides: [ { env: { node: true, }, files: ['.eslintrc.{js,cjs}'], parserOptions: { sourceType: 'script', }, }, ], parserOptions: { ecmaVersion: 'latest', parser: '@typescript-eslint/parser', sourceType: 'module', }, plugins: [ '@typescript-eslint', 'vue', // 2. 加入 prettier 的 eslint 插件 'prettier', // eslint-import-resolver-typescript 插件,@see https://www.npmjs.com/package/eslint-import-resolver-typescript 'import', ], rules: { 'vue/multi-word-component-names': 'off', // 3. 注意要加上这一句,开启 prettier 自动修复的功能 'prettier/prettier': 'error', // turn on errors for missing imports 'import/no-unresolved': 'off', // 对后缀的检测,否则 import 一个ts文件也会报错,需要手动添加'.ts', 增加了下面的配置后就不用了 'import/extensions': [ 'error', 'ignorePackages', { js: 'never', jsx: 'never', ts: 'never', tsx: 'never' }, ], // 只允许1个默认导出,关闭,否则不能随意export xxx 'import/prefer-default-export': ['off'], 'no-console': ['off'], // 'no-unused-vars': ['off'], // '@typescript-eslint/no-unused-vars': ['off'], // 解决vite.config.ts报错问题 'import/no-extraneous-dependencies': 'off', 'no-plusplus': 'off', 'no-shadow': 'off', }, // eslint-import-resolver-typescript 插件,@see https://www.npmjs.com/package/eslint-import-resolver-typescript settings: { 'import/parsers': { '@typescript-eslint/parser': ['.ts', '.tsx'], }, 'import/resolver': { typescript: {}, }, }, }
- .stylelintrc.cjs
npm add -D stylelint stylelint-config-html stylelint-config-recess-order stylelint-config-recommended-vue stylelint-config-standard stylelint-config-standard-scss postcss postcss-html postcss-scss sass
module.exports = { root: true, extends: [ 'stylelint-config-standard', 'stylelint-config-standard-scss', // tips: 本插件也可以替换成 stylelint-config-recommended-scss 'stylelint-config-recommended-vue/scss', 'stylelint-config-html/vue', 'stylelint-config-recess-order', ], overrides: [ // 扫描 .vue/html 文件中的<style>标签内的样式 { files: ['**/*.{vue,html}'], customSyntax: 'postcss-html', }, { files: ['**/*.{css,scss}'], customSyntax: 'postcss-scss', }, ], // 自定义规则 rules: { // 允许 global 、export 、v-deep等伪类 'selector-pseudo-class-no-unknown': [ true, { ignorePseudoClasses: ['global', 'export', 'v-deep', 'deep'], }, ], 'unit-no-unknown': [ true, { ignoreUnits: ['rpx'], }, ], }, }
2、引入 husky
+ lint-staged
+ commitlint
- 先安装git 在终端输入命令 git init
- npm i -D husky lint-staged commitlint @commitlint/cli @commitlint/config-conventional
- npx husky install
- 在
package.json
的scripts里面增加"prepare": "husky install"
package.json
"lint-staged": { "**/*.{html,vue,ts,cjs,json,md}": [ "prettier --write" ], "**/*.{vue,js,ts,jsx,tsx}": [ "eslint --fix" ], "**/*.{vue,css,scss,html}": [ "stylelint --fix" ] },
// commitlint.config.cjs 文件 module.exports = { extends: ['@commitlint/config-conventional'], }
npx husky add .husky/pre-commit "npx --no-install -- lint-staged" npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
3、vite.config.ts 优化
- vite.config.ts
-
import path from 'node:path' import { defineConfig, loadEnv } from 'vite' import uni from '@dcloudio/vite-plugin-uni' import dayjs from 'dayjs' import vue from '@vitejs/plugin-vue' import svgLoader from 'vite-svg-loader' import { visualizer } from 'rollup-plugin-visualizer' import ViteRestart from 'vite-plugin-restart' import Components from 'unplugin-vue-components/vite' // ElementPlusResolver, // AntDesignVueResolver, // VantResolver, // HeadlessUiResolver, // ElementUiResolver import {} from 'unplugin-vue-components/resolvers' import AutoImport from 'unplugin-auto-import/vite' import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' import viteCompression from 'vite-plugin-compression' import viteImagemin from 'vite-plugin-imagemin' import vueSetupExtend from 'vite-plugin-vue-setup-extend' import UnoCSS from 'unocss/vite' import autoprefixer from 'autoprefixer' const htmlPlugin = () => { return { name: 'html-transform', transformIndexHtml(html) { return html.replace('%BUILD_DATE%', dayjs().format('YYYY-MM-DD HH:mm:ss')) }, } } // https://vitejs.dev/config/ export default ({ mode }) => { // mode: 区分生产环境还是开发环境 // process.cwd(): 获取当前文件的目录跟地址 // loadEnv(): 返回当前环境env文件中额外定义的变量 const env = loadEnv(mode, path.resolve(process.cwd(), 'env')) console.log(env) return defineConfig({ plugins: [ uni(), UnoCSS(), htmlPlugin(), svgLoader(), // 打包分析插件 visualizer(), ViteRestart({ // 通过这个插件,在修改vite.config.js文件则不需要重新运行也生效配置 restart: ['vite.config.js'], }), vueSetupExtend(), // 原先引用组件的时候需要在目标文件里面import相关组件,现在就可以直接使用无需在目标文件import了 Components({ dirs: ['src/components'], // 目标文件夹 extensions: ['vue'], // 文件类型 dts: 'src/components.d.ts', // 输出文件,里面都是一些import的组件键值对 // ui库解析器,也可以自定义,需要安装相关UI库 resolvers: [ // VantResolver(), // ElementPlusResolver(), // AntDesignVueResolver(), // HeadlessUiResolver(), // ElementUiResolver() ], }), AutoImport({ imports: ['vue'], dts: 'src/auto-import.d.ts', }), createSvgIconsPlugin({ // 指定要缓存的文件夹 iconDirs: [path.resolve(process.cwd(), 'src/assets/svg')], // 指定symbolId格式 symbolId: 'icon-[dir]-[name]', }), viteCompression(), // 会多出一些.gz文件,如xxx.js.gz,这里默认是不会删除xxx.js文件的,如果想删除也可以增加配置 // 这个图片压缩插件比较耗时,希望仅在生产环境使用 viteImagemin({ gifsicle: { // gif图片压缩 optimizationLevel: 3, // 选择1到3之间的优化级别 interlaced: false, // 隔行扫描gif进行渐进式渲染 // colors: 2 // 将每个输出GIF中不同颜色的数量减少到num或更少。数字必须介于2和256之间。 }, optipng: { // png optimizationLevel: 7, // 选择0到7之间的优化级别 }, mozjpeg: { // jpeg quality: 20, // 压缩质量,范围从0(最差)到100(最佳)。 }, pngquant: { // png quality: [0.8, 0.9], // Min和max是介于0(最差)到1(最佳)之间的数字,类似于JPEG。达到或超过最高质量所需的最少量的颜色。如果转换导致质量低于最低质量,图像将不会被保存。 speed: 4, // 压缩速度,1(强力)到11(最快) }, svgo: { // svg压缩 plugins: [ { name: 'removeViewBox', }, { name: 'removeEmptyAttrs', active: false, }, ], }, }), ], css: { postcss: { plugins: [ autoprefixer({ // 指定目标浏览器 overrideBrowserslist: ['> 1%', 'last 2 versions'], }), ], }, }, resolve: { alias: { '@': path.join(process.cwd(), './src'), }, }, server: { host: '0.0.0.0', hmr: true, port: 7001, // 自定义代理规则 proxy: { // 选项写法 '/api': { target: 'http://localhost:6666', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, ''), }, }, }, }) }
npm i -D vite-svg-loader rollup-plugin-visualizer vite-plugin-restart unplugin-vue-components unplugin-auto-import vite-plugin-svg-icons vite-plugin-compression vite-plugin-vue-setup-extend unocss autoprefixer
vite-plugin-imagemin目前无法安装
-
uno.config.ts
// uno.config.ts import { defineConfig, presetAttributify, presetUno, presetIcons, transformerDirectives, transformerVariantGroup, } from 'unocss' export default defineConfig({ presets: [ presetUno(), // 支持css class属性化,eg: `<button bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600" text="sm white">attributify Button</button>` presetAttributify(), // 支持图标,需要搭配图标库,eg: @iconify-json/carbon, 使用 `<button class="i-carbon-sun dark:i-carbon-moon" />` presetIcons({ scale: 1.2, warn: true, extraProperties: { display: 'inline-block', 'vertical-align': 'middle', }, }), ], transformers: [ transformerDirectives(), // 支持css class组合,eg: `<div class="hover:(bg-gray-400 font-medium) font-(light mono)">测试 unocss</div>` transformerVariantGroup(), ], })
-
main.ts
import 'virtual:svg-icons-register' import 'virtual:uno.css'
-
tsconfig.json
{ "compilerOptions": { "sourceMap": true, "baseUrl": ".", "paths": { "@/*": ["./src/*"] }, "lib": ["esnext", "dom"], "types": ["@dcloudio/types", "@types/wechat-miniprogram", "@uni-helper/uni-app-types"] }, "vueCompilerOptions": { "nativeTags": ["block", "template", "component", "slot"] }, "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], "references": [{ "path": "./tsconfig.node.json" }] }
-
.eslintrc.cjs
globals: { uni: true, },
npm i -D @types/wechat-miniprogram @uni-helper/uni-app-types
npm i -S pinia pinia-plugin-persistedstate
// src/store/index.ts import { createPinia } from 'pinia' import { createPersistedState } from 'pinia-plugin-persistedstate' // 数据持久化 const store = createPinia() store.use( createPersistedState({ storage: { getItem: uni.getStorageSync, setItem: uni.setStorageSync, }, }), ) export default store
// src.main.ts import { createSSRApp } from 'vue' import App from './App.vue' import store from './store' import 'virtual:svg-icons-register' import 'virtual:uno.css' export function createApp() { const app = createSSRApp(App) app.use(store) return { app, } }