vite的preview命令验证了打包命令后的内容成功吗?

安装基础包npm create vite@latest # 这里选择的是Vue+Typescript的组合 cd vue-admin npm install # 先安装基础包 npm install vue-router@4 npm i pinia npm i axios npm install sass --save-dev npm install element-plus --save npm install @element-plus/icons-vue npm install -D unplugin-vue-components unplugin-auto-import npm i eslint -D # 提交规范 npm i lint-staged husky --save-dev npm install @commitlint/cli @commitlint/config-conventional -D 代码规范npm init @eslint/config 接下来会有一堆提示,选择如下:Need to install the following packages: @eslint/create-config Ok to proceed? (y) √ How would you like to use ESLint? · style √ What type of modules does your project use? · esm √ Which framework does your project use? · vue √ Does your project use TypeScript? · No / Yes √ Where does your code run? · browser √ How would you like to define a style for your project? · guide √ Which style guide do you want to follow? · standard-with-typescript √ What format do you want your config file to be in? · JavaScript Checking peerDependencies of eslint-config-standard-with-typescript@latest The config that you've selected requires the following dependencies: eslint-plugin-vue@latest eslint-config-standard-with-typescript@latest @typescript-eslint/eslint-plugin@^5.50.0 eslint@^8.0.1 eslint-plugin-import@^2.25.2 eslint-plugin-n@^15.0.0 eslint-plugin-promise@^6.0.0 typescript@* √ Would you like to install them now? · No / Yes √ Which package manager do you want to use? · npm Installing eslint-plugin-vue@latest, eslint-config-standard-with-typescript@latest, @typescript-eslint/eslint-plugin@^5.50.0, eslint@^8.0.1, eslint-plugin-import@^2.25.2, eslint-plugin-n@^15.0.0, eslint-plugin-promise@^6.0.0, typescript@* 在项目中就会生成一个.eslintrc.cjs文件,接下来配置一下脚本验证一下:"lint": "eslint src/**/*.{js,jsx,vue,ts,tsx} --fix" 然而运行的时候报错了,由于我当前的"typescript": "^5.1.3",而@typescript-eslint/typescript-estree支持的ts版本范围为:=3.3.1 <5.1.0,所以我得降级一下:typescript@5.0.4,在配置eslint路上出现了很多问题,直接提供解决方案:首先是修改.eslintrc.cjs:module.exports = { env: { browser: true, es2021: true }, extends: [ 'plugin:vue/vue3-essential', 'standard-with-typescript' ], parser: "vue-eslint-parser", overrides: [ ], parserOptions: { ecmaVersion: 'latest', sourceType: 'module', project: ["./tsconfig.json"], parser: "@typescript-eslint/parser", extraFileExtensions: ['.vue'] }, plugins: [ 'vue' ], rules: { 'space-before-function-paren': [2, { anonymous: 'always', named: 'never', asyncArrow: 'always' }], 'vue/multi-word-component-names': 0, "space-before-function-paren": 0, "@typescript-eslint/consistent-type-assertions": 0, "@typescript-eslint/ban-types": [ "error", { "extendDefaults": true, "types": { "{}": false } } ] } } 在vite-env.d.ts加上一行注释,忽略检查:// eslint-disable-next-line @typescript-eslint/triple-slash-reference /// 关于eslint配置中遇到的问题,可以参考这个大佬写的,更详细些:Eslint:vue3项目添加eslint(standard规则)commit规范git init 在package.json中新增如下代码,利用它来调用 eslint 和 stylelint 去检查暂存区内的代码"lint-staged": { "*.{vue,js}": [ "npm run lint" ] } 执行:npm pkg set scripts.postinstall="husky install" # 等同于执行npm i,执行过程中会生成.husky文件夹 npm run postinstall npx husky add .husky/pre-commit "npm lint" git add .husky/pre-commit 这样我们执行git commit的时候就会自动执行npm lint。很尴尬,在跑的过程中,报错了node不是内部或外部命令。node -v是木有问题的,大抵是nvm这个工具的问题,所以后面就换了volta来做node的版本控制。npx husky add .husky/commit-msg "npx --no -- commitlint --edit $1" 新建commitlint.config.cjs:module.exports = { extends: ['@commitlint/config-conventional'], rules: { 'type-enum': [2, 'always', [ 'feat', // 新增功能 'update', // 更新功能 'ui', // 样式改动 'fix', // 修复功能bug 'merge', // 合并分支 'refactor', // 重构功能 'perf', // 性能优化 'revert', // 回退提交 'style', // 不影响程序逻辑的代码修改(修改空白字符,格式缩进,补全缺失的分号等) 'build', // 修改项目构建工具(例如 glup,webpack,rollup 的配置等)的提交 'docs', // 文档新增、改动 'test', // 增加测试、修改测试 'chore' // 不修改src或者test的其余修改,例如构建过程或辅助工具的变动 ]], 'scope-empty': [0], // 'scope-empty': [2, 'never'], 作用域不为空 'scope-case': [0], 'subject-full-stop': [0], 'subject-case': [0] } } 修改tsconfig.json:"include": [ //... "commitlint.config.cjs" ], 修改.eslintrc.cjs:project: ["./tsconfig.json", "./commitlint.config.cjs"], git add . # 失败 git commit -m "commit校验" # 成功 git commit -m "feat: commit校验" 设置路径别名import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import path from 'path' const resolve = (dist) => path.resolve(__dirname, dist) export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': resolve('src') }, // 顺便把可以省略的后缀配置一下,在vite中不支持省略.vue extensions: [".js", ".ts", ".tsx", ".jsx"] } }) 修改tsconfig.json,新增:"compilerOptions": { // ... "baseUrl": ".", "paths": { "@/*": ["src/*"] } }, 重置样式在 assets文件夹下新建styles/reset.css:/** * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/) * http://cssreset.com */ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video{ margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; font-weight: normal; vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section{ display: block; } ol, ul, li{ list-style: none; } blockquote, q{ quotes: none; } blockquote:before, blockquote:after, q:before, q:after{ content: ''; content: none; } table{ border-collapse: collapse; border-spacing: 0; } /* custom */ a{ color: #7e8c8d; text-decoration: none; backface-visibility: hidden; -webkit-backface-visibility: hidden; } ::-webkit-scrollbar{ width: 5px; height: 5px; } ::-webkit-scrollbar-track-piece{ background-color: rgba(0, 0, 0, 0.2); border-radius: 6px; -webkit-border-radius: 6px; } ::-webkit-scrollbar-thumb:vertical{ height: 5px; background-color: rgba(125, 125, 125, 0.7); border-radius: 6px; -webkit-border-radius: 6px; } ::-webkit-scrollbar-thumb:horizontal{ width: 5px; background-color: rgba(125, 125, 125, 0.7); border-radius: 6px; -webkit-border-radius: 6px; } html, body{ width: 100%; font-family: "Arial", "Microsoft YaHei", "黑体", "宋体", "微软雅黑", sans-serif; } body{ line-height: 1; -webkit-text-size-adjust: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } html{ overflow-y: scroll; } /*清除浮动*/ .clearfix:before, .clearfix:after{ content: " "; display: inline-block; height: 0; clear: both; visibility: hidden; } .clearfix{ *zoom: 1; } /*隐藏*/ .dn{ display: none; } 使用ScssVite 提供了对 .scss, .sass, .less, .styl 和 .stylus 文件的内置支持。没有必要为它们安装特定的 Vite 插件,但必须安装相应的预处理器依赖。一般我们会在项目中定义一些主题色:// variable.scss $font-color-gray:rgb(147,147,147); 或者是一些封装好的集合样式:// mixins.scss @mixin line-clamp($lines) { word-break: break-all; display: -webkit-box; overflow: hidden; text-overflow: ellipsis; -webkit-line-clamp: $lines; -webkit-box-orient: vertical; } @mixin ellipsis() { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } 然后我们在vite.config.js中配置:css: { preprocessorOptions: { scss: { additionalData: '@import "@/assets/styles/variable.scss";@import "@/assets/styles/mixins.scss";' } } } 删除目录中的style.css,新建styles/common.scss :// common.scss @import url('./reset.css'); 然后在main.ts中引入:import '@/assets/styles/common.scss' 这样全局样式就初始化了,接下来测试一下variable.scss和mixins.scss是否起作用,修改HelloWorld.vue查看是否为灰色且两行省略: 配置路由现在要来配置路由,希望有这样的结果:- 登录页 - 带菜单栏的框架 - 主页 - 人员管理 - 客户管理 - 员工管理 - 404页 所以新建以下文件:在这个过程中我们会遇到几个问题:在编写路由的时候我们引入组件,必须有.vue后缀;import xxx from '@/xxx'时会报错,是因为你没有在上面提到的那样在tsconfg.json中设置baseUrl和paths值。由于layout文件中要嵌套子路由,所以layout中要加入router-view: 其他的文件只要写成这样就行: 新建router文件夹:- router -hooks # 后期做登录校验和鉴权用的 - routes - index.ts # 总输出文件 - others.ts # 不需要layout这一层的路由均可以放在这里 - person.ts # 人员管理模块 - index.ts # 总输出文件 接下里是各个文件的内容:// person.ts export default [ { path: '/person', name: 'Person', meta: { title: '人员管理' }, redirect: '/person/customer', children: [ { path: '/person/customer', name: 'PersonCustomer', meta: { title: '客户管理' }, component: () => import('@/views/person/customer/index.vue') }, { path: '/person/staff', name: 'PersonStaff', meta: { title: '员工管理' }, component: () => import('@/views/person/staff/index.vue') } ] } ]; // others.ts export default [ { path: '/login', name: 'Login', meta: { title: '登录' }, component: () => import('@/views/login/index.vue') } ]; // router/routes/index.ts import Layout from '@/views/layout/index.vue'; import personRoutes from './person'; import otherRoutes from './others'; export default [ { path: '/', name: 'Layout', component: Layout, children: [ { path: '/', name: 'Index', meta: { title: '主页' }, component: () => import('@/views/index/index.vue') }, ...personRoutes, ] }, ...otherRoutes, { path: '/404', name: 'NotFound', meta: { title: '404' }, component: () => import('@/views/404/index.vue') }, { path: "/:pathMatch(.*)", redirect: "/404", name:'ErrorPage', meta: { title: '' }, } ]; 先抛开hooks文件夹,简单的写一下index.ts:// router/index.ts import routes from "./routes"; export default routes; 新建一个src/plugins/index.ts,之前我们注册内容的时候都是直接放在main.ts中,不太容易维护,所以以后统一在这里挂载:// src/plugins/index.ts import { createRouter, createWebHashHistory } from 'vue-router'; import routes from '@/router/index'; export default (app: any) => { // 注册路由 const router = createRouter({ history: createWebHashHistory(), routes }) app.use(router); } 不要忘了修改App.vue: import { createApp } from 'vue' import '@/assets/styles/common.scss' import App from './App.vue' import installPlugins from '@/plugins'; const app = createApp(App); installPlugins(app); app.mount('#app') 这样就可以测试了:http://127.0.0.1:5173/#/ http://127.0.0.1:5173/#/login http://127.0.0.1:5173/#/person http://127.0.0.1:5173/#/person/customer http://127.0.0.1:5173/#/person/staff 如果在配置过程中发现报错:找不到模块“xxx.vue”或其相应的类型声明,则在vite-env.d.ts中新增:declare module '*.vue' { import type { DefineComponent } from 'vue'; const vueComponent: DefineComponent<{}, {}, any>; export default vueComponent; } 使用element plus如果您使用 Volar,请在 tsconfig.json 中通过 compilerOptions.type 指定全局组件类型。// tsconfig.json { "compilerOptions": { // ... // 然而这个配置在后期打包的时候报错了... "types": ["element-plus/global"] } } 这里采用了按需引入的方式,如果对体积不追求的,可以采用完整引入:// vite.config.ts import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import path from 'path' // 新增 import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' const resolve = (dist) => path.resolve(__dirname, dist) export default defineConfig({ plugins: [ vue(), // 新增 AutoImport({ resolvers: [ElementPlusResolver()] }), // 新增 Components({ resolvers: [ElementPlusResolver()] }) ], resolve: { alias: { '@': resolve('./src') }, extensions: [".js", ".ts", ".tsx", ".jsx"] }, css: { preprocessorOptions: { scss: { additionalData: '@import "@/assets/styles/variable.scss";@import "@/assets/styles/mixins.scss";' } } } }) element plus中日期等组件默认是英文,所以我们把组件改为中文:修改App.vue: 这样就会出现中文了。关于引入的两个插件,这里解释一下:unplugin-vue-components用于自动识别Vue模板中使用的组件,自动按需导入和注册;unplugin-auto-import可以在vite、webpack等环境下自动按需导入配置库常用的API,如Vue的ref,不需要手动import,所以我们可以配置一下,并删除一些API的引入:export default defineConfig({ plugins: [ // ... AutoImport({ imports: [ 'vue', 'vue-router', 'pinia' ], eslintrc: { enabled: true, filepath: './.eslintrc-auto-import.json', globalsPropValue: true }, resolvers: [ElementPlusResolver()] }), // ... ], }) 保存生效后,auto-imports.d.ts 会自动填充内容,并且会在项目根目录生成 .eslintrc-auto-import.json eslint 全局变量配置。然后修改tsconfg.json和.eslintrc.cjs:// tsconfg.json "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "commitlint.config.cjs", "auto-imports.d.ts"], // .eslintrc.cjs project: ["./tsconfig.json", "./commitlint.config.cjs", './.eslintrc-auto-import.json'], 忽略 auto-imports.d.ts ESLint 校验# .eslintignore auto-imports.d.ts 这里需要注意一下:不是全部 API,例如 Vue Router 的 createRouter 就不会导入。具体可以自动导入的 API 参考 unplugin-auto-import/src/presets生成 .eslintrc-auto-import.json 文件后如不需要增加配置建议将 enabled: true 设置为 false,否则每次都会生成这个文件。配置完可以删除页面中的一些引用,发现是没有问题的。 测试一下组件: 这样页面上就会显示按钮了。自动按需引入的原理是通过识别