前言
在多人协作的工程之下,我们需要一个规范指导我们写出风格类似的代码
比如
- 代码缩进格式,双引号还是单引号
- 代码是否格式化
- commit信息是否清晰
- typescript的类型是否定义清楚
如果没有这些规范,那么代码除了逻辑不好懂,还会乱七八糟的缩进格式以及lint的红线,以及本来可以通过规范来规避的bug,这一切会让开发过程十分难受。更别提多人协作的项目,简直要人命。
正文
所以我们会使用如下几个工具
- prettier 对代码格式化检查
- stylelint 规范样式文件
- eslint 规范javascript/typescript代码
- tsc 检查typescript类型
- commitlint 检查commit信息格式
- lint-staged 整合上面几个工具,在提交代码的时候统一检查
stylelint,eslint,prettier都是有vscode插件,记得在vscode里面把它们打开,这样可以实时看到问题在哪,不要等到上传代码的时候再改。(默认大家的ide都是vscode)
Stylelint
pnpm i stylelint stylelint-config-standard stylelint-config-prettier stylelint-config-recess-order stylelint-config-standard-scss stylelint-prettier -D
在root目录创建.stylelintrc.js
内容如下
module.exports = {
// 注册 stylelint 的 prettier 插件
plugins: ['stylelint-prettier'],
// 继承一系列规则集合
extends: [
// standard 规则集合
'stylelint-config-standard',
// standard 规则集合的 scss 版本
'stylelint-config-standard-scss',
// 样式属性顺序规则
'stylelint-config-recess-order',
// 接入 Prettier 规则
'stylelint-config-prettier',
'stylelint-prettier/recommended'
],
// 配置 rules
rules: {
// 开启 Prettier 自动格式化功能
'prettier/prettier': true
}
};
Prettier
pnpm i prettier -D // 使用自己喜欢的包管理工具
在root目录创建.prettierrc.js
module.exports = {
printWidth: 80, //一行的字符数,如果超过会进行换行,默认为80
tabWidth: 2, // 一个 tab 代表几个空格数,默认为 2 个
useTabs: false, //是否使用 tab 进行缩进,默认为false,表示用空格进行缩减
singleQuote: true, // 字符串是否使用单引号,默认为 false,使用双引号
semi: true, // 行尾是否使用分号,默认为true
trailingComma: 'none', // 是否使用尾逗号
bracketSpacing: true // 对象大括号直接是否有空格,默认为 true,效果:{ a: 1 }
};
尽管我们装了prettier的插件,但是vscode在格式化的时候并不是默认使用prettier来格式化。 我们需要配置一下
首先我们按F1
输入 format 会看到 Format Document With
选择prettier作为默认的格式化工具
如果想要在保存的的时候格式化,那么按ctrl ,, 输入format,并且勾选format on save
如果需要某些文件不要格式化,那么可以添加一个.prettierignore,原理和.gitignore一样
Eslint
pnpm i eslint -D
在root目录创建.eslintrc.js
内容如下
// eslint-disable-next-line no-undef
module.exports = {
settings: {
react: {
version: 'detect' // React version. "detect" automatically picks the version you have installed.
}
},
env: {
browser: true,
es2021: true
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended',
// 1. 接入 prettier 的规则
'prettier',
'plugin:prettier/recommended'
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true
},
ecmaVersion: 'latest',
sourceType: 'module'
},
// 2. 加入 prettier 的 eslint 插件
plugins: ['react', '@typescript-eslint', 'prettier'],
rules: {
// 3. 注意要加上这一句,开启 prettier 自动修复的功能
'prettier/prettier': [
'error',
{
endOfLine: 'auto'
}
],
quotes: ['error', 'single'],
semi: ['error', 'always'],
'react/react-in-jsx-scope': 'off',
'reactdisplay-name': 'off',
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': ['error'],
'react/prop-types': 0,
'react/display-name': 0
}
};
这里先依次安装几个eslint插件
pnpm i @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-prettier eslint-plugin-prettier eslint-plugin-react -D
根据插件的前缀scope,大概能看出他们的作用
检查typescript
- @typescript-eslint/eslint-plugin
- @typescript-eslint/parser
因为eslint有自己的格式化规则,所以需要解决它和prettier的冲突
- eslint-config-prettier
- eslint-plugin-prettier
检查react代码
- eslint-plugin-react
现在简单来看看.eslintrc.js里面的内容
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended',
// 1. 接入 prettier 的规则
'prettier',
'plugin:prettier/recommended'
],
这里是继承了已经写好的规则,非常容易理解,一些重复的规则可以直接继承,类似tsconfig里面的extends
parser: '@typescript-eslint/parser',
eslint并不能解析typescript,所以需要指定parser
plugins: ['react', '@typescript-eslint', 'prettier'],
刚刚安装的plugin
rules: {
// 3. 注意要加上这一句,开启 prettier 自动修复的功能
'prettier/prettier': [
'error',
{
endOfLine: 'auto'
}
],
quotes: ['error', 'single'],
semi: ['error', 'always'],
'react/react-in-jsx-scope': 'off',
'reactdisplay-name': 'off',
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': ['error'],
'react/prop-types': 0,
'react/display-name': 0
}
这里可能出现一种情况,在rules里面可能需要添加一条这样的规则
'react/prop-types': 0,
因为react本身使用了另外一种工具来定义类型,所以会和typescript的类型校验冲突,所以我们需要把它关掉
如果需要忽略某地方不做lint,和prettier同理,添加.eslintignore即可
配置commit规范
配置commit规范分为两个部分
- 一个是使用工具cz-cli来输出格式化的commit工具
- 一个是通过commitlint来校验commit合法
cz-cli
pnpm i -g commitizen
首先全局安装commitizen
有两种途径能输出和cz-cli(commitizen)一样的commit messgae
- 直接使用Visual Studio Code Commitizen Support插件
安装完成之后按F1,输入commit
第一步选择你的commit类型
- feaure 新功能
- fix 修复bug
- docs 文档注释
- style 样式ui
- refactor 重构
- …………
第二步 输入功能概述或者影响范围
第三步 用两句话描述你干了什么,从这里开始后面的都不是必填的选项了
后面的可以自己探索
- 使用
npx cz或者git cz来进行使用cz-cli
使用步骤和上面的插件一模一样
如果想要使用自己title
在package.json里面添加
"config": {
"commitizen": {
"path": "cz-conventional-changelog",
"types": {
"新功能": {
"description": "新增的功能",
"title": "新功能"
},
"修复BUG": {
"description": "修复 BUG、问题",
"title": "修复BUG"
},
"文档": {
"description": "添加文档或修改注释",
"title": "文档"
},
"格式": {
"description": "调整代码格式,未修改代码逻辑(比如修改空格、格式化、缺少分号等)",
"title": "格式"
},
"重构": {
"description": "代码重构,既没修复 bug 也没有添加新功能",
"title": "重构"
},
"测试": {
"description": "添加或修改测试代码",
"title": "测试"
},
"编译": {
"description": "影响编译的更改相关,比如打包路径更改、npm 过程更改等",
"title": "编译"
},
"回滚 ": {
"description": "版本回滚相关",
"title": "回滚"
}
}
}
},
如果团队里面大家都用上了这个工具,commit本应该无需校验,但是你懂的有人就是乱提交
所以我们需要
Commitlint
pnpm i @commitlint/config-conventional @commitlint/cli -D
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
注意!!! 如果你配置中文的commit title,现在commitlint不支持验证中文,作者正在支持这个特性。 我们需要添加特殊的配置忽略中文
在commitlint.config.js加上
rules: {
'type-enum': [
2,
'always',
['新功能', '修复BUG', '文档', '格式', '重构', '测试', '编译', '回滚']
],
'subject-empty': [0],
'type-empty': [0]
}
在提交的时候校验你的代码
husky
当我们为了防止有人不规范自己的代码,直接忽略lint的提示就上传代码,我们需要在commit的时候直接校验他的代码防止他传上去。
配置husky,我们可以很简单的使用git hooks,在commit完成后检查。
pnpm add husky -D
在package.json的script里面加一条
"prepare": "husky install"
接着运行
pnpm run prepare
npx husky add .husky/pre-commit "npx tsc --noEmit && npx --no -- lint-staged"
npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
在根目录我们可以看到
我们的commitlint挂在commit-msg这个git hooks上,也就是创建commit的时候
接下来我们配置lint-staged
lint-staged
pnpm add lint-staged -D
在package.json
首先在script里面添加
"lint:script": "eslint --ext .js,.jsx,.ts,.tsx --fix --quiet ./",
"lint:style": "stylelint --fix \"src/**/*.{css,less}\"",
接着再添加
"lint-staged": {
"**/*.{js,jsx,tsx,ts}": [
"npm run lint:script",
"git add --force"
],
"**/*.less": [
"npm run lint:style",
"git add --force"
]
},
整个package.json
{
"name": "lint-validation",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"prepare": "husky install",
"lint:script": "eslint --ext .js,.jsx,.ts,.tsx --fix --quiet ./",
"lint:style": "stylelint --fix \"src/**/*.{css,less}\""
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@commitlint/cli": "^17.0.3",
"@commitlint/config-conventional": "^17.0.3",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"@typescript-eslint/eslint-plugin": "^5.31.0",
"@typescript-eslint/parser": "^5.31.0",
"@vitejs/plugin-react": "^2.0.0",
"eslint": "^8.20.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.30.1",
"husky": "^8.0.1",
"lint-staged": "^13.0.3",
"prettier": "^2.7.1",
"stylelint": "^14.9.1",
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-recess-order": "^3.0.0",
"stylelint-config-standard": "^26.0.0",
"stylelint-config-standard-scss": "^5.0.0",
"stylelint-prettier": "^2.0.0",
"typescript": "^4.6.4",
"vite": "^3.0.0"
},
"lint-staged": {
"**/*.{js,jsx,tsx,ts}": [
"npm run lint:script",
"git add --force"
],
"**/*.less": [
"npm run lint:style",
"git add --force"
]
},
"config": {
"commitizen": {
"path": "cz-conventional-changelog",
"types": {
"新功能": {
"description": "新增的功能",
"title": "新功能"
},
"修复BUG": {
"description": "修复 BUG、问题",
"title": "修复BUG"
},
"文档": {
"description": "添加文档或修改注释",
"title": "文档"
},
"格式": {
"description": "调整代码格式,未修改代码逻辑(比如修改空格、格式化、缺少分号等)",
"title": "格式"
},
"重构": {
"description": "代码重构,既没修复 bug 也没有添加新功能",
"title": "重构"
},
"测试": {
"description": "添加或修改测试代码",
"title": "测试"
},
"编译": {
"description": "影响编译的更改相关,比如打包路径更改、npm 过程更改等",
"title": "编译"
},
"回滚 ": {
"description": "版本回滚相关",
"title": "回滚"
}
}
}
}
}
成功的效果图
补充
如果package.json中type为module,那么需要将上述的.prettierrc.js .stylelintrc.js 等配置文件的格式后缀改为cjs