模板技术信息:
- 构建工具 vite 2.7.2
- 项目框架 vue 3.2.25
- 网络请求 axios 0.24.0
- 路由配置 vue-router 4.0.12
- 状态管理 pinia 2.0.9 & vuex 4.0.2
- 编程语言 TypeScript 4.4.4
- 数据模拟 Mockjs 1.1.0
模版工程化配置:
- CSS 预编译 sass 1.46.0 / less 4.1.2 / stylus 0.56.0
- 代码规范 eslint 8.6.0 + prettier 2.5.1
- Git hooks husky 7.0.4 + lint-staged 12.3.3
- 提交规范 commitizen 4.2.4 + commitlint + standard-version 9.3.2
- 单元测试 vue-test-utils + jest
文章系列目录
前言
Vue3 项目模版搭建(一) 后续文章,内容主要为模版项目中的工程化基础配置,主要包含有:代码提交规范、日志生成及发布 以及单元测试 等等。
项目
github地址: vue3-vite-ts-pnpm
代码规范
日常多人协作时,代码风格会略有不同。因而在项目协作中代码规范统一是必不可少的!而且良好的代码规范不仅可以让代码看起来更加整洁,而且可以提升代码的审查效率。
在这里则使用 eslint 和 prettier 进行代码风格的基本规范。
配置 EditorConfig
VS Code 商店安装 EditorConfig for VS Code 插件,帮助统一编辑器风格
配置 EditorConfig
在根目录下创建一个名为 .editorconfig 的配置文件,内容如下:
# Editor configuration, see http://editorconfig.org
root = true # 是否为根目录,支持不同层级单独配置
[*] # 适用所有文件
indent_style = space # tab | space
indent_size = 4 # 缩进
end_of_line = crlf # lf | cr | crlf
charset = utf-8 # 字符集
trim_trailing_whitespace = true # 自动切掉首尾空格
insert_final_newline = true # 末尾空行
[*.{js,ts,vue,jsx,tsx}] # 如何处理这些文件
indent_size = 2 # 缩进为 2
[*.md] # 如何处理这些文件
trim_trailing_whitespace = false # 不自动切掉首尾空格
配置 Prettier
VS Code 商店安装 Prettier - Code formatter 插件,帮助将代码格式化为统一风格
安装 prettier
pnpm i prettier -D
配置 prettier
在根目录下创建一个名为 .prettierrc 的配置文件,内容如下:
{
"useTabs": false,
"tabWidth": 2,
"printWidth": 80,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"semi": true,
"arrowParens": "avoid"
}
更多 prettierrc 字段配置说明可参考 eslint规则在项目中的整合(js、prettier、vue、typescript) 或 官方文档
使用 prettier
通过 prettier 命令格式化统一代码风格,快捷键:Alt + Shift + F 或 opt + Shift + F
npx prettier --write . # . 表示所有文档
配置 ESlint
VS Code 商店安装 ESLint 插件,帮助将代码格式化为统一风格
安装 eslint
pnpm i eslint -D
配置 ESLint
通过下面命令初始化 eslint 配置
npx eslint --init
按照命令提示相对应的选项,如下图所示:
PS:注意在最后一步不要选择
Yes 使用 npm 自动下载相关的依赖包,会出现报错。主要是版本相关和缺少依赖包的错误。
手动安装
eslint 配置所需要的相应依赖包
pnpm i eslint-plugin-vue eslint-config-airbnb-base eslint-plugin-import @typescript-eslint/eslint-plugin @typescript-eslint/parser -D
安装后会自动在根目录下生成 .eslintrc.js 配置文件,使用 opt + Shift + F 快捷键可格式化配置文件代码,添加如下规则:
rules: {
'linebreak-style': 0,
},
配置 Vue 规则
vue3 规则配置
extends: [
'plugin:vue/essential',
'airbnb-base',
'plugin:vue/vue3-recommended', // vue3 的规则。vue2 使用 plugin:vue/recommended
],
vue 文件解析 parser
// 添加文件错误解析 parser
parser: 'vue-eslint-parser', // 解析 .vue 文件
ts 支持
对于 airbnb-base 规则,需单独添加 TypeScript 的支持
pnpm i eslint-config-airbnb-typescript -D
extends: [
'plugin:vue/essential',
'airbnb-base',
'airbnb-typescript/base', // 添加 typescript 支持
'plugin:vue/vue3-recommended', // vue3 的规则。vue2 使用 plugin:vue/recommended
],
使用 ESlint
在 package.json 文件中添加如下命令
"scripts": {
...,
"lint": "eslint src/**/*.{vue,ts}",
"lint:fix": "eslint src/**/*.{vue,ts} --fix",
"lint:create": "eslint --init"
},
执行下面命令修复所有内容 eslint 相关问题,若此时仍有报错,可先了解是否为下面描述的 冲突及问题处理 相关问题,如果不是的话,则可能需手动进行修复处理。
pnpm run lint:fix
修改
lint:fix 命令如下
"lint:fix": "eslint src/**/*.{vue,ts} --fix",
冲突及问题处理
ts 文件解析问题
无法解析处理 ts 文件,详情见 How to fix eslintrc The file does not match your project config?。.eslintrc.ts 添加下面配置信息:
parserOptions: {
...,
tsconfigRootDir: __dirname,
project: './tsconfig.json',
},
vue 文件解析问题
无法解析处理 .vue 文件,.eslintrc.ts 添加下面配置信息:
parserOptions: {
...,
extraFileExtensions: ['.vue'],
},
解决 Prettier 与 ESLint 的冲突问题
这两个的规则有时存在冲突,一般情况下以 Prettier 优先;安装插件并在 .eslintrc.ts 添加相应配置信息
pnpm i eslint-plugin-prettier eslint-config-prettier -D
extends: [
'plugin:vue/essential',
'airbnb-base',
"airbnb-typescript/base", // 添加 typescript 支持
"plugin:vue/vue3-recommended", // 添加高亮行内容到文件 (vue3 的规则)。vue2 使用 plugin:vue/recommended
'plugin:prettier/recommended', // 添加解决冲突插件
],
解决通过 @ 引入的路径问题
使用路径别名如 @ 可能会出现无法找到相应路径问题错误;安装插件并在 .eslintrc.ts 添加相应配置信息
pnpm i eslint-import-resolver-alias eslint-import-resolver-typescript -D
在tsconfig.json 中添加
{
"compilerOptions": {
"baseUrl": ".",
"types": ["vite/client", "node"],
"paths": {
"@/*": ["./src/*"]
}
}
}
在 .eslintrc.js 中添加
module.exports = {
...
settings: {
"import/parsers": {
"@typescript-eslint/parser": [".ts", ".tsx"]
},
"import/resolver": {
alias: {
map: [["@", "./src"]],
extensions: [".js", ".jsx"]
},
typescript: {
alwaysTryTypes: true,
project: "./tsconfig.json"
}
}
},
...
}
解决 defineProps 等未定义的错误
使用 <script setup> 标签时,defineProps 等不再需要显示定义,不过这样 eslint 规则会报错,所以需要进行相应的配置
module.exports = {
...
globals: {
defineProps: "readonly",
defineEmits: "readonly",
defineExpose: "readonly",
withDefaults: "readonly"
}
...
};
解决函数参数无法修改问题
添加忽略参数无法修改规则的白名单,具体可参考 优雅解决: assignment to property of function parameter 'state'
"no-param-reassign": [
"error",
{
"props": true,
"ignorePropertyModificationsFor": [
"e", // for e.returnvalue
"ctx", // for Koa routing
"req", // for Express requests
"request", // for Express requests
"res", // for Express responses
"response", // for Express responses
"state" // for vuex state
]
}
]
其它 rules 配置
module.exports = {
rules: {
"prettier/prettier": ["error", { endOfLine: "auto" }], // 解决 prettier 行尾报错
"vue/multi-word-component-names": "off", // 组件名称是否多单词
"vue/no-multiple-template-root": "off", // 启用根层级多个标签
"vue/script-setup-uses-vars": "error", // 标记 setup 中的变量为 used
"import/prefer-default-export": "off", // 是否需要含有默认导出
"vue/no-v-model-argument": "off", // 'v-model' directives require no argument
}
};
husky + lint-staged
husky 添加勾子在相应的时机触发,进行 lint 检查、单元测试、代码美化等操作;lint-staged 则是对个人提交代码的验证规范及约束。更多可查看 husky + lint-staged + commitlint 安装配置
安装配置 husky
安装 husky
pnpm i husky --save-dev
配置 husky
在 package.json 中添加 prepare 脚本
{
...
"scripts": {
...
"prepare": "husky install", // 新增prepare脚本
}
...
}
执行脚本命令,会创建 .husky/ 目录并指定该目录为 git hooks 所在的目录
pnpm run prepare
执行命令添加 git hooks,执行下面命令后 .husky/ 目录下会增加pre-commit的 shell 脚本文件。当在执行 git commit 命令时会执行该脚本
npx husky add .husky/pre-commit "npm run lint"
说明:
🙅 如果手动添加或修改 husky 的 git hooks 脚本文件或内容,则会出现下面错误
fatal: cannot run .husky/pre-commit: No such file or directory
正确做法(通过命令的方式添加脚本文件及内容信息)
npx husky add .husky/pre-commit "npm run lint"
PS:如果手动修改了出现上面找不到文件问题,最简单粗暴的方式是把 .husky/pre-commit 删除再执行上面命令重新添加
安装配置 lint-staged
安装 lint-staged
pnpm i lint-staged --save-dev
配置 lint-staged
在 package.json 中添加命令及配置内容如下
{
"scripts": {
...
"lint": "lint-staged --allow-empty",
...
},
"lint-staged": {
"src/**/!(*.min).js": [
"prettier --write",
"eslint --fix"
],
"src/**/*.{ts,vue}": [
"prettier --write",
"eslint --fix"
],
"src/**/*.{ts,js,vue,html,css,scss,sass,stylus}": [
"prettier --write"
]
},
}
提交规范
提交规范相关内容在该文章 Git Commit 规范及 CHANGELOG 定制生成 里面讲述的比较详细,这里就不再重新赘述啦!
注意⚠️:
- 将文章里面的
npm改为pnpm执行依赖安装,保持统一 git cz采用全局安装方式,如果采用项目安装的话,命令执行后相应包使用的是npm进行安装
单元测试
项目中添加单元测试可以更有效的的保证代码的质量,测试代码编写基本类型,之前写过一遍关于 RN 基于 Jest + testing-library 单元测试实践 测试文章,主要是通过模拟预期操作来进行对应代码的自动化测试过程。
安装依赖
安装测试依赖
pnpm i jest@26.6.3 ts-jest@26.5.6 @vue/test-utils@next vue-jest@next @types/jest eslint-plugin-jest -D
说明:jest 和 ts-jest 可能存在版本冲突,运行测试内容会报错,需要指定相同的版本。如均为版本 26详情见 issues#351
安装测试需要的 babel 依赖
pnpm i @babel/core @babel/preset-env @babel/preset-typescript @vue/babel-plugin-jsx -D
pnpm i babel-jest@26
说明:babel-jest 由于版本问题,如果安装最新版 ^27,会引起 TypeError: babelJest.getCacheKey is not a function 的错误,所以需要安装 ^26 版本。详情见 issues#344
配置 jest
在根目录下添加 jest.config.js 配置文件,并添加下面内容
module.exports = {
clearMocks: true,
coverageDirectory: 'coverage',
coverageProvider: 'v8',
moduleFileExtensions: ['vue', 'js', 'json', 'jsx', 'ts', 'tsx', 'node'],
testMatch: ['**/test/unit/**/?(*.)+(unit|test|spec).[jt]s?(x)'],
testPathIgnorePatterns: ['/node_modules/'],
transform: {
'^.+\\.jsx?$': 'babel-jest',
'^.+\\.vue?$': 'vue-jest',
'^.+\\.tsx$': 'ts-jest'
},
moduleNameMapper: {
// 支持源代码中相同的 `@` -> `src` 别名
'^@/(.*)$': '<rootDir>/src/$1'
},
preset: 'ts-jest',
testEnvironment: 'jsdom',
collectCoverage: true,
collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx,vue}', '!**/node_modules/**']
// coverageReporters: ["text", "text-summary", "html"],
};
在根目录下添加 babel.config.js 配置文件,内容如下
module.exports = {
presets: [
["@babel/preset-env", { targets: { node: "current" } }],
"@babel/preset-typescript"
],
plugins: ["@vue/babel-plugin-jsx"]
};
在 tsconfig.json 配置中添加下面内容
{
"compilerOptions": {
"types": ["vite/client", "node", "jest"]
},
"include": [
...
"tests/**/*.ts"
]
}
在eslintrc.js 配置文件中添加下面内容
extends: [
...
'plugin:jest/recommended',
...
],
执行测试
在 package.json 中添加测试命令
{
"scripts": {
...
"test": "jest",
...
}
}
在项目根目录下添加测试目录及文件 test/unit/Test.spec.ts,内容如下:
import { mount } from '@vue/test-utils';
import HelloWorld from '@/components/HelloWorld.vue';
describe('Welcome Component Test', () => {
const wrapper = mount(HelloWorld, {
props: { msg: 'Hello Test!' }
});
it('load component', () => {
const html = wrapper.text();
console.log(html);
expect(html).toContain('Hello Test!');
});
});
执行下面测试命令
pnpm run test
问题处理
- 根目录下添加
env.d.ts类型引用说明文件,处理test内模块引用问题。
eslint忽略文件.eslintignore添加需要忽略的配置文件
总结
文章知识回顾。我们可以了解到项目工程化的一些基本配置信息,主要包含以下内容知识:
eslint + prettier代码规范husky + lint-staged代码提交规范commitize + commitlint + standard-version代码规范提交及日志自动生成vue-test-utils + jest单元测试
参考
从 0 搭建项目模板(vue3)
Git Commit 规范及 CHANGELOG 定制生成
RN 基于 Jest + testing-library 单元测试实践