一、创建vue3脚手架项目
1. 打开本地前端文件目录
2. 执行命令npm init vue@latest(vue3+vite+typescript)
3. 执行npm install或pnpm install下载依赖
4. 前端项目工程化
前端工程化:一种将前端开发流程系统化、规范化和自动化的方法,旨在提高前端开发的效率、可维护性和可扩展性。它涵盖了许多方面,包括项目结构、代码质量、自动化工具、性能优化等,以确保前端开发团队能够更高效地协作和交付高质量的前端应用程序。
- 项目结构:定义清晰的项目目录结构,使开发人员能够轻松查找和组织代码、样式和资源文件。
- 版本控制:使用版本控制系统(如Git)来跟踪和管理代码的变化,以便多个开发人员可以协同工作,并轻松回滚到以前的版本。
- 自动化构建:使用构建工具(如Webpack、Grunt、Gulp、vite等)来自动化任务,如代码编译、压缩、打包和资源优化,以减少手动工作和减小文件大小。
- 模块化开发:采用模块化的代码结构,使开发人员能够更好地管理和复用代码,提高可维护性。
- 包管理器:使用包管理工具(如npm、Yarn)来管理和安装项目依赖,确保开发环境的一致性。
- 代码质量:引入代码风格检查工具(如ESLint、TSLint)和单元测试框架,以确保代码质量和可靠性。
- 自动化部署:使用持续集成/持续部署(CI/CD)工具来自动化应用程序的部署和发布过程,以确保快速且可靠的交付。
- 性能优化:优化前端性能,包括加载时间、资源压缩、懒加载等,以提供更好的用户体验。
- 文档和注释:编写清晰的文档和代码注释,以便其他开发人员能够理解和使用你的代码。
因此,我们需在当前项目中添加Husky、lint-staged、ESLint、Stylelint、Prettier、@commitlint/cli、@commitlint/config-conventional等工具包。
前端工程化流程图
先在package.json中配置通用的脚本:
"scripts": {
# 构建项目
"build": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=8192 pnpm vite build",
# 生成打包分析,在电脑上执行完成后会自动打开界面
"build:analyze": "cross-env NODE_OPTIONS=--max-old-space-size=8192 pnpm vite build --mode analyze",
"build:test": "cross-env NODE_OPTIONS=--max-old-space-size=8192 pnpm vite build --mode test",
# 用于生成标准化的git commit message
"commit": "czg",
# 运行项目
"dev": "pnpm vite",
# 执行 eslint 校验,并修复部分问题
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
# 执行 prettier 格式化(该命令会对项目所有代码进行 prettier 格式化,请谨慎执行)
"lint:prettier": "prettier --write .",
# 执行 stylelint 格式化
"lint:stylelint": "stylelint \"**/*.{vue,css,less,scss}\" --fix --cache --cache-location node_modules/.cache/stylelint/",
"lint:lint-staged": "lint-staged",
# 安装git hooks
"prepare": "husky install",
# 预览打包后的内容(先打包在进行预览)
"preview": "npm run build && vite preview",
# 运行项目
"serve": "npm run dev",
# 对打包结果进行 gzip 测试
"test:gzip": "npx http-server dist --cors --gzip -c-1",
# 类型检查
"type:check": "vue-tsc --noEmit --skipLibCheck",
# 生成changelog
"log": "conventional-changelog -p angular -i CHANGELOG.md -s"
}
-
Husky
Husky 是一个用于前端开发的 Node.js 工具,它主要用于在 Git 提交钩子(Git Hooks)中运行脚本。Git 提交钩子是在 Git 版本控制系统的特定事件发生时执行的自定义脚本,例如在代码提交前执行一些检查或验证。
Husky 的主要用途是帮助开发团队在代码提交前执行一些预定义的操作,以确保代码的质量和一致性。常见的用例包括:
- 代码风格检查: 在提交代码之前运行 ESLint、Prettier 或其他代码风格检查工具,以确保代码遵循一致的编码风格。
- 单元测试: 在提交前运行单元测试,以确保代码没有破坏现有功能。
- 提交消息验证: 检查提交消息是否符合规范,以便生成清晰的提交日志。
Husky 可以配置为在不同的 Git 提交钩子事件中运行脚本,例如 pre-commit(在提交前运行)、pre-push(在推送前运行)等。通过在项目的 package.json 文件中配置 Husky,开发团队可以轻松集成这些检查和验证步骤,以确保代码的质量和一致性,并减少潜在的问题。通过 Husky 和类似工具的使用,开发团队可以更轻松地维护一致的代码质量和开发流程。
Husky 是前端工程化中的一个工具,可以帮助开发团队实现自动化、规范化和高质量的前端开发流程。通过配置 Husky 钩子,可以确保代码质量、版本控制、协作和规范化流程得到有效管理,从而提高项目的整体质量和开发效率。
安装与配置:
-
使用npm 或 Yarn安装
#钩子工具 npm install husky --save-dev
-
启用Husky
执行以下命令启用Husky,执行完命令后,项目根路径中会多出一个
.husky
的文件夹。npx husky install
必须通过git管理项目!
- 初始化Git仓库:git init
- 添加文件到Git仓库:git add .
- 提交初始化版本:git commit -m “build: 项目初始化”
如果考虑后续会多次用到该命令的话,可以在package.json中加一条命令:
"prepare": "husky install"
,后续运行npm run prepare
即可。 -
配置钩子
在.husky文件中创建两个的shell脚本文件:per-commit.sh和commit-msg。这两个脚本将在相应的git hook中被调用。per-commit钩子在提交之前触发,即在执行 git commit 命令时触发。commit-msg 钩子是在提交消息被保存到版本控制系统之后触发的,但在提交被真正完成之前执行。
-
per-commitsh
在per-commit中执行lint-staged检查并格式化提交的代码。
#!/bin/sh . "$(dirname "$0")/_/husky.sh" . "$(dirname "$0")/common.sh" # Format and submit code according to lintstagedrc.js configuration npm run lint:lint-staged
-
commit-msg
在commit-msg中执行commitlint检查commit message的规范。
#!/bin/sh # shellcheck source=./_/husky.sh . "$(dirname "$0")/_/husky.sh" . "$(dirname "$0")/common.sh" npx --no-install commitlint --edit "$1"
注意,在windows 上,如果是通过 Git Bash 去进行Git操作的,Git hook中的语句含有
yarn
命令时,会导致Git hook失效,这时候需要再额外添加一个common.sh
文件,内容如下:#!/bin/sh command_exists () { command -v "$1" >/dev/null 2>&1 } # Workaround for Windows 10, Git Bash and Yarn if command_exists winpty && test -t 1; then exec < /dev/tty fi
同时在
per-commit.sh
和commit-msg
引入 -
-
lint-staged
lint-staged 是一个用于在 Git 暂存区(Staging Area)中运行代码检查工具的工具。它通常与 Husky 和 Prettier 或 ESLint 等代码检查工具一起使用,以确保在提交代码之前只检查和格式化已经修改的代码,从而提高开发团队的效率和代码质量。 lint-staged 与 Husky 结合使用时,通过在提交代码前运行 lint-staged 命令,来在提交前进行代码检查和格式化。
安装与配置:
-
使用npm 或 Yarn安装
#只校验和格式化修改的内容 npm install lint-staged@12.3.7 --save-dev
-
添加lint-staged配置
在package.json添加如下内容:
"lint-staged": { "*.{js,jsx,ts,tsx}": [ "eslint --fix", "prettier --write" ], "{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [ "prettier --write--parser json" ], "package.json": [ "prettier --write" ], "*.vue": [ "eslint --fix", "prettier --write", "stylelint --fix" ], "*.{scss,less,styl,html}": [ "stylelint --fix", "prettier --write" ], "*.md": [ "prettier --write" ] }
lint-staged会去匹配提交文件属于哪种类型的文件,并根据以上配置文件对应的文件类型执行相应的命令。
-
-
ESLint
ESLint 是一个强大的 JavaScript 代码质量检查工具,它有助于提高代码的可维护性、一致性和可读性。通过配置和使用 ESLint,开发团队可以确保项目中的 JavaScript 代码符合一致的标准和最佳实践,从而提高开发效率和代码质量。
安装与配置:
-
使用npm 或 Yarn安装
# eslint npm install eslint@8.13.0 --save-dev # 关闭一些不必要的或者是与 prettier 冲突的 eslint 规则 npm install eslint-config-prettier@8.5.0 --save-dev # 用于检查 JavaScript 模块的导入语句。它可以帮助您确保您的导入语句是正确的,并且符合您的项目的约定 npm install eslint-plugin-import@2.29.1 --save-dev # 将 ESLint 的一些样式规则替换为 Prettier 的规则 npm install eslint-plugin-prettier@4.0.0 --save-dev # 允许我们使用ESLint检查.vue文件中的<template>和<script>部分,以及.js文件中的Vue代码。 npm install eslint-plugin-vue@8.6.0 --save-dev # eslint默认是不支持检测typescript的,我们需要安装它的扩展,让它支持typescript的语法 npm install @typescript-eslint/parser --save-dev # eslint设置typescript的规则 npm install @typescript-eslint/eslint-plugin --save-dev
-
在根目录创建一个
.eslintrc.cjs
文件,存放eslint的规范要求:module.exports = { // 指定此配置文件为根配置文件,即停止在父级目录中寻找其他配置文件。 root: true, // 指定代码的环境是下面这些环境 env: { browser: true, node: true, es6: true, }, // 指定解析器,识别.vue文件,需下载eslint-plugin-vue parser: 'vue-eslint-parser', // 解析器配置选项 parserOptions: { parser: '@typescript-eslint/parser', ecmaVersion: 2020, sourceType: 'module' }, // 继承规则 extends: [ // 使用该规则集来检查Vue3项目中的JavaScript代码 'plugin:vue/vue3-recommended', // 使用该规则集来检查Vue3项目中的TypeScript代码 'plugin:@typescript-eslint/recommended', // 使用该规则集来检查Vue3项目中的代码符不符合prettier格式化 'plugin:prettier/recommended', ], // 自定义其它规则 rules: { // 使<script setup>中变量标记为已被使用,当该变量在<template>中已被使用 'vue/script-setup-uses-vars': 'error', // 在Vue中,建议使用kebab-case(短横线分隔命名)来命名事件,而不是camelCase(驼峰式命名),当前设置为关闭 'vue/custom-event-name-casing': 'off', // 禁止定义前使用,当前设置为关闭 'no-use-before-define': 'off', // 禁止存在未使用过的变量,以下划线开头的变量除外 'no-unused-vars': [ 'error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_', }, ], // 要求或禁止函数圆括号之前有一个空格,当前设置为关闭 'space-before-function-paren': 'off', // 用于强制指定 Vue 组件中的属性顺序,当前设置为关闭 'vue/attributes-order': 'off', // Vue规定每个文件应该只包含一个组件的规则,当前设置为关闭 'vue/one-component-per-file': 'off', // 检查HTML标签结束括号后是否应该换行,当前设置为关闭 'vue/html-closing-bracket-newline': 'off', // 限制单个HTML标签上的属性数量,当前设置为关闭 'vue/max-attributes-per-line': 'off', // 要求在多行的HTML元素内容前必须要有一个换行,当前设置为关闭 'vue/multiline-html-element-content-newline': 'off', // 要求单行HTML元素内容应在新行上,当前设置为关闭 'vue/singleline-html-element-content-newline': 'off', // 要求HTML特性名称应该使用短横线命名(也称为kebab-case),即所有字母都应小写,并且单词之间用短横线连接,当前设置为关闭 'vue/attribute-hyphenation': 'off', // 要求每个prop都必须指定其默认值,当前设置为关闭 'vue/require-default-prop': 'off', // 要求具有名称的emits选项由$emit()触发,当前设置为关闭 'vue/require-explicit-emits': 'off', // 确保HTML中的自闭合标签正确地使用了自闭合的语法 'vue/html-self-closing': [ 'error', { html: { void: 'always', normal: 'never', component: 'always', }, svg: 'always', math: 'always', }, ], // 在Vue中,组件的名称应该是多单词的,并且要么用kebab-case(短横线分隔命名),要么用PascalCase(大驼峰式命名),当前设置为关闭 'vue/multi-word-component-names': 'off', // 函数和类的方法需要显式返回类型,当前设置为关闭 '@typescript-eslint/explicit-function-return-type': 'off', // 不允许any类型,当前设置为关闭 '@typescript-eslint/no-explicit-any': 'off', // 不允许除导入语句外的require语句,当前设置为关闭 '@typescript-eslint/no-var-requires': 'off', // 不允许空函数,当前设置为关闭 '@typescript-eslint/no-empty-function': 'off', // 不允许未定义前使用变量,当前设置为关闭 '@typescript-eslint/no-use-before-define': 'off', // 不允许@ts-<directive>注释或要求在指令后进行说明,当前设置为关闭 '@typescript-eslint/ban-ts-comment': 'off', // 不允许某些类型,当前设置为关闭 '@typescript-eslint/ban-types': 'off', // 不允许使用!后置运算符作不为空的断言,当前设置为关闭 '@typescript-eslint/no-non-null-assertion': 'off', // 在导出的函数和类的公共方法上需要显式的返回类型和参数类型,当前设置为关闭 '@typescript-eslint/explicit-module-boundary-types': 'off', // 禁止存在未使用过的变量,以下划线开头的变量除外 '@typescript-eslint/no-unused-vars': [ 'error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_', }, ], }, }
-
在根目录创建一个
.eslintignore
文件,忽视某些文件或文件夹:*.sh node_modules *.md *.woff *.ttf .vscode .idea dist /public /docs .husky .local /bin Dockerfile
-
在package.json 文件中添加脚本用来运行 Eslint 相关
"scripts": { "lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix", "lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"", "lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/", "lint:lint-staged": "lint-staged", }
-
-
Stylelint
Stylelint 是一个用于检查和规范 CSS(层叠样式表)和 CSS 预处理器(如 Sass 和 Less)代码质量的工具。类似于 ESLint 用于 JavaScript 代码的检查和规范,Stylelint 旨在帮助开发人员和团队发现和修复 CSS 代码中的问题、错误和不规范之处,以确保代码的一致性、可维护性和可读性。
安装与配置:
-
使用npm 或 Yarn安装
# 本人使用less样式语言,先安装less npm install less@4.1.2 --save-dev # stylelint npm install stylelint@14.7.1 --save-dev # 配置 stylelint 和 prettier 兼容 npm install stylelint-config-prettier@9.0.3 --save-dev # 专门检验css文件 npm install stylelint-config-recommended@7.0.0 --save-dev # 检验vue文件中的样式 npm install stylelint-config-recommended-vue@1.4.0 --save-dev # 配置 stylelint 拓展插件 npm install stylelint-config-standard@25.0.0 --save-dev # 提供了一种自动化的方式来管理你的 CSS 样式表中的属性排列。它可以检查并修复 CSS、SCSS 和 Less 文件中属性的顺序 npm install stylelint-order@5.0.0 --save-dev # 借助JavaScript的力量转换CSS npm install postcss@8.4.12 --save-dev # 用PostCSS语法解析html中的样式 npm install postcss-html@1.4.1 --save-dev # 用PostCSS语法解析LESS npm install postcss-less@6.0.0 --save-dev
-
在根目录创建一个
stylelint.config.cjs
文件,存放stylelint的规范要求:module.exports = { // 指定此配置文件为根配置文件,即停止在父级目录中寻找其他配置文件。 root: true, plugins: ['stylelint-order'], // 继承规则,使用下面规则集来检查Vue3项目中的样式 extends: ['stylelint-config-standard', 'stylelint-config-prettier'], // 使用postcss-html插件来解析HTML文件中的CSS customSyntax: 'postcss-html', // 自定义其它规则 rules: { // 不能CSS文件中调用了一个不存在的函数 'function-no-unknown': null, // 检查CSS类选择器命名规则,当前设置为关闭 'selector-class-pattern': null, // 禁止未知的伪类选择器,ignorePseudoClasses列表中的除外 'selector-pseudo-class-no-unknown': [ true, { ignorePseudoClasses: ['global'], }, ], // 禁止未知的伪元素选择器,ignorePseudoElements列表中的除外 'selector-pseudo-element-no-unknown': [ true, { ignorePseudoElements: ['v-deep'], }, ], // 禁止未知的 at 规则,ignoreAtRules列表中的除外 'at-rule-no-unknown': [ true, { ignoreAtRules: [ 'tailwind', 'apply', 'variants', 'responsive', 'screen', 'function', 'if', 'each', 'include', 'mixin', ], }, ], // 禁止空源,当前设置为关闭 'no-empty-source': null, // 在字符串周围指定单引号或双引号,当前设置为关闭 'string-quotes': null, // 禁止无效的命名网格区域,当前设置为关闭 'named-grid-areas-no-invalid': null, // 禁止使用 Unicode 字节顺序标记 (BOM) 'unicode-bom': 'never', // 禁止较低特异性的选择器覆盖较高特异性的选择器,当前设置为关闭 'no-descending-specificity': null, // 禁止字体系列中缺少通用系列关键字,当前设置为关闭 'font-family-no-missing-generic-family-keyword': null, // 在冒号声明后必须有一个空格 'declaration-colon-space-after': 'always-single-line', // 在冒号声明前不允许使用空格 'declaration-colon-space-before': 'never', // 要求规则前必须始终有一个空行,忽略注释后面的规则以及忽略嵌套规则及其父节点的第一个子节点 'rule-empty-line-before': [ 'always', { ignore: ['after-comment', 'first-nested'], }, ], // 禁止未知单位,ignoreUnits列表除外 'unit-no-unknown': [true, { ignoreUnits: ['rpx'] }], // 指定声明块中内容的顺序 'order/order': [ [ 'dollar-variables', 'custom-properties', 'at-rules', 'declarations', { type: 'at-rule', name: 'supports', }, { type: 'at-rule', name: 'media', }, 'rules', ], { severity: 'warning' }, ], }, // 忽略所有js/jsx/tsx/ts文件 ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts'], // 覆盖配置 overrides: [ { files: ['*.vue', '**/*.vue', '*.html', '**/*.html'], extends: ['stylelint-config-recommended'], rules: { 'keyframes-name-pattern': null, 'selector-pseudo-class-no-unknown': [ true, { ignorePseudoClasses: ['deep', 'global'], }, ], 'selector-pseudo-element-no-unknown': [ true, { ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'], }, ], }, }, { files: ['*.less', '**/*.less'], customSyntax: 'postcss-less', extends: ['stylelint-config-standard', 'stylelint-config-recommended-vue'], }, ], }
-
在根目录创建一个
.stylelintignore
文件,忽视某些文件或文件夹:/dist/* /public/* public/*
-
-
Prettier
Prettier 是一个代码格式化工具,用于自动化地格式化代码,使其符合一致的编码风格和规范。它支持多种编程语言,包括 JavaScript、TypeScript、HTML、CSS、JSON、Markdown 等,旨在减轻开发人员在代码风格上的决策负担,从而提高代码的可读性和一致性。
安装与配置:
-
使用npm 或 Yarn安装
npm install prettier@2.6.2 --save-dev
-
在根目录创建一个
prettier.config.cjs
文件,存放prettier的规范要求:module.exports = { // 一行最多 100 字符 printWidth: 100, // 语句末尾可以加分号 semi: false, // vue script和style标签中是否缩进,开启可能会破坏编辑器的代码折叠 vueIndentScriptAndStyle: true, // 单引号 singleQuote: true, // 尾部逗号设置,es5是尾部逗号兼容es5,none就是没有尾部逗号,all是指所有可能的情况,需要node8和es2017以上的环境 trailingComma: 'all', // 文章换行,默认情况下会对你的markdown文件换行进行format会控制在printwidth以内 proseWrap: 'never', // html中的空格敏感性 htmlWhitespaceSensitivity: 'strict', // 行尾换行符,默认是lf endOfLine: 'auto', }
-
-
commitlint
-
@commitlint/cli
是一个用于检查 Git 提交消息是否符合指定的规范的命令行工具。它通常与 Husky 和 Commitizen 等工具一起使用,以确保团队在提交代码时遵循一致的提交消息规范。 -
@commitlint/config-conventional
是一个预定义的配置包,用于与@commitlint/cli
结合使用,以规范化 Git 提交消息的格式。它基于Conventional Commits 规范
,这是一种约定俗成的提交消息格式,旨在提供一致、清晰且易于理解的提交消息,特别适用于团队协作和自动生成变更日志(changelog)。Conventional Commits 规范要求提交消息遵循以下结构:
<类型>(可选范围): <描述>
[可选的正文]
[可选的脚注]
@commitlint/config-conventional
配置包定义了 Conventional Commits 规范的验证规则,以确保提交消息遵循上述格式。如果提交消息不符合规范,@commitlint/cli
将生成相应的错误消息,并拒绝提交。使用
@commitlint/config-conventional
可以帮助团队在项目中实施统一的提交消息格式,从而改进提交历史的可读性和维护性,并为自动生成变更日志提供了便利。它通常与 Husky 和其他前端工程化工具一起使用,以确保提交消息的一致性。 -
czg
是轻量级,简单快速,零配置的交互式命令行工具,用于生成标准化的 git commit message,搭配cz-git使用 -
cz-git
一款工程性更强,轻量级,高度自定义,标准输出格式的 commitizen 适配器。 -
conventional-changelog-cli
是一个用于生成 Vue3 项目的 changelog文件的工具
安装与配置:
-
使用npm 或 Yarn安装
#校验commit message npm install @commitlint/cli@16.2.3 --save-dev npm install @commitlint/config-conventional@16.2.1 --save-dev npm install czg@1.3.11 --save-dev npm install cz-git@1.3.11 --save-dev npm install conventional-changelog-cli@2.2.2 --save-dev
-
在根目录创建一个
commitlint.config.cjs
文件,存放commitlint的规范要求:const fs = require('fs') const path = require('path') const { execSync } = require('child_process') const scopes = fs .readdirSync(path.resolve(__dirname, 'src'), { withFileTypes: true }) .filter((dirent) => dirent.isDirectory()) .map((dirent) => dirent.name.replace(/s$/, '')) // precomputed scope const scopeComplete = execSync('git status --porcelain || true') .toString() .trim() .split('\n') .find((r) => ~r.indexOf('M src')) ?.replace(/(\/)/g, '%%') ?.match(/src%%((\w|-)*)/)?.[1] ?.replace(/s$/, '') /** @type {import('cz-git').UserConfig} */ module.exports = { ignores: [(commit) => commit.includes('init')], extends: ['@commitlint/config-conventional'], rules: { 'body-leading-blank': [2, 'always'], 'footer-leading-blank': [1, 'always'], 'header-max-length': [2, 'always', 108], 'subject-empty': [2, 'never'], 'type-empty': [2, 'never'], 'subject-case': [0], 'type-enum': [ 2, 'always', [ 'feat', 'fix', 'perf', 'style', 'docs', 'test', 'refactor', 'build', 'ci', 'chore', 'revert', 'wip', 'workflow', 'types', 'release', ], ], }, prompt: { /** @use `yarn commit :f` */ alias: { f: 'docs: fix typos', r: 'docs: update README', s: 'style: update code format', b: 'build: bump dependencies', c: 'chore: update config', }, customScopesAlign: !scopeComplete ? 'top' : 'bottom', defaultScope: scopeComplete, scopes: [...scopes, 'mock'], allowEmptyIssuePrefixs: false, allowCustomIssuePrefixs: false, // English typesAppend: [ { value: 'wip', name: 'wip: work in process' }, { value: 'workflow', name: 'workflow: workflow improvements' }, { value: 'types', name: 'types: type definition file changes' }, ], // 中英文对照版 // messages: { // type: '选择你要提交的类型 :', // scope: '选择一个提交范围 (可选):', // customScope: '请输入自定义的提交范围 :', // subject: '填写简短精炼的变更描述 :\n', // body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n', // breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n', // footerPrefixsSelect: '选择关联issue前缀 (可选):', // customFooterPrefixs: '输入自定义issue前缀 :', // footer: '列举关联issue (可选) 例如: #31, #I3244 :\n', // confirmCommit: '是否提交或修改commit ?', // }, // types: [ // { value: 'feat', name: 'feat: 新增功能' }, // { value: 'fix', name: 'fix: 修复缺陷' }, // { value: 'docs', name: 'docs: 文档变更' }, // { value: 'style', name: 'style: 代码格式' }, // { value: 'refactor', name: 'refactor: 代码重构' }, // { value: 'perf', name: 'perf: 性能优化' }, // { value: 'test', name: 'test: 添加疏漏测试或已有测试改动' }, // { value: 'build', name: 'build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)' }, // { value: 'ci', name: 'ci: 修改 CI 配置、脚本' }, // { value: 'revert', name: 'revert: 回滚 commit' }, // { value: 'chore', name: 'chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)' }, // { value: 'wip', name: 'wip: 正在开发中' }, // { value: 'workflow', name: 'workflow: 工作流程改进' }, // { value: 'types', name: 'types: 类型定义文件修改' }, // ], // emptyScopesAlias: 'empty: 不填写', // customScopesAlias: 'custom: 自定义', }, }
-
在
package.json
中修改指定commitizen使用的适配器"config": { "commitizen": { "path": "node_modules/cz-git" } }
-
5. 配置环境变量
- Vite 使用
dotenv
从环境目录中的文件加载额外的环境变量 cross-env
可以保证你在不同的操作系统上设置环境变量的一致性
先使用npm 或 Yarn安装相关依赖
npm install dotenv@16.0.0 --save-dev
npm install cross-env@7.0.3 --save-dev
其次生成env文件
.env
共享环境变量.env.development
本地开发环境变量.env.test
测试环境变量.env.production
正式环境变量
只有以
VITE_
开头的变量会被嵌入到客户端侧的包中,你可以在项目代码中这样访问它们:console.log(import.meta.env.VITE_PROT);
配置env.d.ts文件,为环境变量增加智能提示
/// <reference types="vite/client" />
interface ImportMetaEnv {
//定义提示信息 数据是只读的无法被修改
readonly VITE_APP_ENV: string
}
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
6. vite.config.js通用配置
import { fileURLToPath, URL } from 'node:url'
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig(({ mode, command }) => {
const env = loadEnv(mode, process.cwd())
const { VITE_APP_ENV } = env
return {
// 部署生产环境和开发环境下的URL。
// 默认情况下,vite 会假设你的应用是被部署在一个域名的根路径上
// 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
base: VITE_APP_ENV === 'production' ? '/' : '/',
plugins: [vue()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
'~': fileURLToPath(new URL('./', import.meta.url))
}
},
// vite 相关配置
server: {
port: 3100,
host: true,
open: true,
proxy: {
'/dev-api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, '')
}
}
},
// 移除打包时的@charset警告
// 警告: "@charset" must be the first rule in the file
css: {
postcss: {
plugins: [
{
postcssPlugin: 'internal:charset-removal',
AtRule: {
charset: (atRule) => {
if (atRule.name === 'charset') {
atRule.remove()
}
}
}
}
]
}
}
}
})
7. 其它插件配置
先在根目录下新建目录vite/plugins
,然后新建文件index.ts(拼接各种插件并包装成函数),在vite.config.ts文件中导入替换原plugins配置,例子如下:
index.ts
import vue from '@vitejs/plugin-vue'
import createAutoImport from './auto-import'
import createSvgIcon from './svg-icon'
import createCompression from './compression'
import createSetupExtend from './setup-extend'
export default function createVitePlugins(viteEnv: any, isBuild = false) {
const vitePlugins = [vue()]
vitePlugins.push(createAutoImport())
vitePlugins.push(createSetupExtend())
vitePlugins.push(createSvgIcon(isBuild))
isBuild && vitePlugins.push(...createCompression(viteEnv))
return vitePlugins
}
vite.config.ts
import createVitePlugins from './vite/plugins'
// plugins: [vue()],
plugins: createVitePlugins(env, command === 'build'),
-
按需自动导入API配置
下载安装依赖
npm install unplugin-auto-import@0.17.6 --save-dev
在
vite/plugins
目录下新建auto-import.tsimport autoImport from 'unplugin-auto-import/vite' export default function createAutoImport() { return autoImport({ imports: ['vue', 'vue-router', 'pinia'], dts: true }) }
在根目录下新建文件auto-imports.d.ts或者执行npm run dev会自动生成
/* eslint-disable */ /* prettier-ignore */ // @ts-nocheck // noinspection JSUnusedGlobalSymbols // Generated by unplugin-auto-import export {} declare global { const EffectScope: typeof import('vue')['EffectScope'] const computed: typeof import('vue')['computed'] const createApp: typeof import('vue')['createApp'] const customRef: typeof import('vue')['customRef'] const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] const defineComponent: typeof import('vue')['defineComponent'] const effectScope: typeof import('vue')['effectScope'] const getCurrentInstance: typeof import('vue')['getCurrentInstance'] const getCurrentScope: typeof import('vue')['getCurrentScope'] const h: typeof import('vue')['h'] const inject: typeof import('vue')['inject'] const isProxy: typeof import('vue')['isProxy'] const isReactive: typeof import('vue')['isReactive'] const isReadonly: typeof import('vue')['isReadonly'] const isRef: typeof import('vue')['isRef'] const markRaw: typeof import('vue')['markRaw'] const nextTick: typeof import('vue')['nextTick'] const onActivated: typeof import('vue')['onActivated'] const onBeforeMount: typeof import('vue')['onBeforeMount'] const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'] const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'] const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] const onDeactivated: typeof import('vue')['onDeactivated'] const onErrorCaptured: typeof import('vue')['onErrorCaptured'] const onMounted: typeof import('vue')['onMounted'] const onRenderTracked: typeof import('vue')['onRenderTracked'] const onRenderTriggered: typeof import('vue')['onRenderTriggered'] const onScopeDispose: typeof import('vue')['onScopeDispose'] const onServerPrefetch: typeof import('vue')['onServerPrefetch'] const onUnmounted: typeof import('vue')['onUnmounted'] const onUpdated: typeof import('vue')['onUpdated'] const provide: typeof import('vue')['provide'] const reactive: typeof import('vue')['reactive'] const readonly: typeof import('vue')['readonly'] const ref: typeof import('vue')['ref'] const resolveComponent: typeof import('vue')['resolveComponent'] const shallowReactive: typeof import('vue')['shallowReactive'] const shallowReadonly: typeof import('vue')['shallowReadonly'] const shallowRef: typeof import('vue')['shallowRef'] const toRaw: typeof import('vue')['toRaw'] const toRef: typeof import('vue')['toRef'] const toRefs: typeof import('vue')['toRefs'] const toValue: typeof import('vue')['toValue'] const triggerRef: typeof import('vue')['triggerRef'] const unref: typeof import('vue')['unref'] const useAttrs: typeof import('vue')['useAttrs'] const useCssModule: typeof import('vue')['useCssModule'] const useCssVars: typeof import('vue')['useCssVars'] const useLink: typeof import('vue-router')['useLink'] const useRoute: typeof import('vue-router')['useRoute'] const useRouter: typeof import('vue-router')['useRouter'] const useSlots: typeof import('vue')['useSlots'] const watch: typeof import('vue')['watch'] const watchEffect: typeof import('vue')['watchEffect'] const watchPostEffect: typeof import('vue')['watchPostEffect'] const watchSyncEffect: typeof import('vue')['watchSyncEffect'] } // for type re-export declare global { // @ts-ignore export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue' import('vue') }
在tsconfig.app.json文件中include中添加"auto-imports.d.ts"语句
在同级文件index.ts中导入并使用
import vue from '@vitejs/plugin-vue' import createAutoImport from './auto-import' export default function createVitePlugins(viteEnv: any, isBuild = false) { const vitePlugins = [vue()] vitePlugins.push(createAutoImport()) // ... return vitePlugins }
记得重启编辑器才会生效
-
轻松命名组件名称配置
下载安装依赖
npm install unplugin-vue-setup-extend-plus@1.0.1 --save-dev
在
vite/plugins
目录下新建setup-extend.tsimport setupExtend from 'unplugin-vue-setup-extend-plus/vite' export default function createSetupExtend() { return setupExtend({}) as any }
在同级文件index.ts中导入并使用
import vue from '@vitejs/plugin-vue' import createSetupExtend from './setup-extend' export default function createVitePlugins(viteEnv: any, isBuild = false) { const vitePlugins = [vue()] vitePlugins.push(createSetupExtend()) // ... return vitePlugins }
-
用于生成 svg 雪碧图
下载安装依赖
npm install vite-plugin-svg-icons@2.0.1 --save-dev
在
vite/plugins
目录下新建svg-icon.tsimport { createSvgIconsPlugin } from 'vite-plugin-svg-icons' import path from 'path' export default function createSvgIcon(isBuild: boolean) { return createSvgIconsPlugin({ // 指定需要缓存的图标文件夹 iconDirs: [path.resolve(process.cwd(), 'src/assets/icons/svg')], // 指定symbolId格式 symbolId: 'icon-[name]', // 图片是否压缩 svgoOptions: isBuild }) }
在同级文件index.ts中导入并使用
import vue from '@vitejs/plugin-vue' import createSvgIcon from './svg-icon' export default function createVitePlugins(viteEnv: any, isBuild = false) { const vitePlugins = [vue()] vitePlugins.push(createSvgIcon(isBuild)) // ... return vitePlugins }
main.ts文件引入
//svg插件需要配置代码 import 'virtual:svg-icons-register';
在src/components目录下新建SvgIcon/index.vue组件
<script setup lang="ts"> const props = defineProps({ name: { type: String, require: true }, width: { type: String, default: "16px" }, height: { type: String }, className: { type: String }, }) const _height = computed(() => { return props.height ? props.height : props.width; }) const iconName = computed(() => { return `#${props.name}`; }) </script> <template> <svg :class="className" :style="{ width, height: _height }"> <use :xlink:href="iconName"></use> </svg> </template> <style scoped> </style>
再全局注册该组件,后续在src/assets/icons/svg目录中放置svg文件,最后在文件中引入
// 举例 <svg-icon name="file-icon" width="28px" height="20px"/>
-
压缩文件资源
vite-plugin-compression是一个基于Vite的插件,用于gzip或Brotli压缩你的资源,从而减少页面的加载时间和网络带宽,提高用户访问速度和体验。
注意用gzip压缩资源的话,nginx也得配置:
## # `gzip` Settings # # gzip on; gzip_static on; gzip_disable "msie6"; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_buffers 16 8k; gzip_http_version 1.1; gzip_min_length 256; gzip_types text/plain text/ application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon; client_max_body_size 2048m; # 上传文件大小控制 # TimeOut # 配置段: http, server, location client_header_timeout 600s;
下载安装依赖
npm install vite-plugin-compression@0.5.1 --save-dev
在
vite/plugins
目录下新建compression.tsimport compression from 'vite-plugin-compression' export default function createCompression(env: any) { const { VITE_BUILD_COMPRESS } = env const plugin = [] if (VITE_BUILD_COMPRESS) { const compressList = VITE_BUILD_COMPRESS.split(',') if (compressList.includes('gzip')) { plugin.push( compression({ ext: '.gz', deleteOriginFile: false }) ) } if (compressList.includes('brotli')) { plugin.push( compression({ ext: '.br', algorithm: 'brotliCompress', deleteOriginFile: false }) ) } } return plugin }
在同级文件index.ts中导入并使用
import vue from '@vitejs/plugin-vue' import createCompression from './compression' export default function createVitePlugins(viteEnv: any, isBuild = false) { const vitePlugins = [vue()] isBuild && vitePlugins.push(...createCompression(viteEnv)) // ... return vitePlugins }
-
使用unocss(css原子化)
UnoCSS是即时原子CSS引擎,设计为灵活和可扩展。核心是不固执己见的,所有CSS实用程序都是通过预设提供的。
先下载安装依赖
npm install -D unocss
在
vite/plugins
目录下index.ts
文件中导入并使用import vue from '@vitejs/plugin-vue' import Unocss from 'unocss/vite' export default function createVitePlugins(viteEnv: any, isBuild = false) { const vitePlugins = [vue(),Unocss()] // ... return vitePlugins }
创建
uno.config.ts
文件:// uno.config.ts import { defineConfig } from 'unocss' export default defineConfig({ // ...UnoCSS options })
将
virtual:uno.css
添加到您的主入口文件:// main.ts import 'virtual:uno.css'
官网查询样式用法https://unocss.dev/interactive/
中文官网https://unocss-cn.pages.dev/
二、插件简单介绍
前置:
ES6(https://es6.ruanyifeng.com/),
typescript(https://www.tslang.cn/docs/handbook/functions.html),
node.js(https://nodejs.org/zh-cn),
vue-router(https://router.vuejs.org/zh/),
pinjia()
1. unplugin-config
该工具可生成Web应用程序的配置文件,并允许对全局变量进行定制化,无需重新打包即可外部修改。
文档网站:https://github.com/kirklin/unplugin-config/blob/main/README.zh-cn.md
2. @vitejs/plugin-vue-jsx
该工具使vue支持jsx语法(是一种用于描述 UI 的 JavaScript 语法扩展。允许开发者在 JavaScript 代码中编写类似 HTML 的标记语言)。
3. dayjs
Day.js是一个极简的JavaScript库,可以为现代浏览器解析、验证、操作和显示日期和时间。
文档官网:https://dayjs.fenxianglu.cn/
4. picocolors
picocolors是一个可以在终端修改输出字符样式的npm白,说直白点就是给字符添加颜色
文档官网:https://github.com/alexeyraspopov/picocolors?tab=readme-ov-file#picocolors
5. lodash-es
Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。Lodash-es是Lodash的ES6 模块版本,只有你实际使用的部分会被打包,减小了最终的文件大小。
文档官网:https://www.lodashjs.com/
6. axios
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
7. tinycolor
一个轻量级的颜色操作库,让您在JavaScript环境中轻松实现颜色的处理与转换。
文档官网:https://github.com/scttcper/tinycolor
8. treeify
treeify
是一个JavaScript库,它可以将JS对象转换成可视的深度缩进树形结构,非常适合在控制台打印。这个小巧的工具模仿了Unix系统中的tree
命令,让你能清晰地查看和理解复杂的数据结构,尤其是在处理文件系统目录树时效果尤为显著。
文档官网:https://github.com/notatestuser/treeify
9. directory-tree
基于目录生成一个JavaScript的object。
文档官网:https://github.com/mihneadb/node-directory-tree
10. esno
是一个集成了 esbuild 的 Node.js 运行时环境增强版,它不仅简化了 TypeScript 和 ECMAScript 模块(ESM)的加载流程,还通过自动化的 CJS/ESM 模式切换与缓存机制,提供了无与伦比的速度与便捷性。tsx的别名,ts的jsx。
文档官网:https://tsx.is/
11. fs-extra
fs-extra
是一个功能丰富的Node.js库,它在原生fs
模块的基础上增加了许多实用功能,旨在提供更为便捷和强大的文件及目录操作。通过fs-extra
,开发者可以更加高效地处理文件系统的各种任务,同时享受到更友好的API设计和更完善的错误处理机制。
文档官网:https://github.com/jprichardson/node-fs-extra?spm=a2c6h.12873639.article-detail.8.345d40dfpfkZuw
12. mitt
Mitt 是一个在 Vue.js 应用程序中使用的小型事件总线库。该库允许组件进行通信,而不必过度依赖父级或子级组件之间的 props。
评论区