项目工程化配置--lint
1.husky
husky的作用就是形成git hooks钩子的形成,在git的各种操作,会调用husky对应的一些操作
// 安装husky
npm install husky
// husky初始化(作用就是生成.husky文件)
npx husky init
// .husky/_/里面的文件就是一些git会调用的一些hooks,外面的是自己写的hooks,因为里面的一些hooks定义了解释器和执行脚本,所以在外部自己写的一些hooks就不需要要去配置,如果里面没有这些操作,则需要在自定义hooks里面写上该解释器和加载该脚本
1.1 pre-commit
# pre-commit 里面就是在commit之前会调用的,在这里可以使用eslint,stylelint,prettier校验,格式化代码
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx eslint && npx stylelint && npx prettier
1.1.1 为什么使用lint-staged
# pre-commit文件
# 按道理应该如上这样去写,但是这里使用lint-staged,是因为上面的代码每次都是全量扫描及修复,会很浪费性能,所以使用lint-staged只对暂存区进行校验,你可以理解为lint-stage是一个集合操作,把所有的lint操作都集合在了一起,只对暂存区生效
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged -c .lintstagedrc.json
lint-staged需要一个配置文件,该配置文件告诉了lint-staged如何操作,如下所示,对代码进行了eslint,prettier和stylelint校验和修复
//.lintstagedrc.json
{
"{src,public}/**/*": [
"pnpm exec eslint -c .eslintrc.cjs --ignore-path .eslintignore --fix src/ public/",
"prettier --write --ignore-unknown src/"
],
"{src,public}/**/*.{css,scss,vue,html}": [
"pnpm exec stylelint --config .stylelintrc.json --fix \"src/**/*.{css,scss,vue}\" \"public/**/*.html\""
]
}
1.2 commit-msg
# commit-msg 里面就是在commit提交信息前所进行的操作,这里进行的操作是对commit的信息进行校验,具体校验规则会放到单独的commitlint讲解
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx --no -- commitlint --edit ${1}
至此,husky的作用就完成了。
2.lint-staged里面的lint
代码lint阶段分为eslint,prettier,stylelint
2.1 eslint
eslint用来校验js,根据解析器生成ast树去检查语法和词法,可以使用插件进行扩展就可以对vue、typescript等文件进行校验,可以使用别人提前规范好的config,直接使用他们的规则
# 安装eslint
npm intsall eslint
# 初始化,创建配置文件
npx eslint --init
[!IMPORTANT] 注意:eslint@8版本生成的配置文件为.eslintrc.js,eslint@9版本以后生成的配置文件为eslint.config.mjs,并且eslint@9移除了样式格式化,样式格式化建议采用prettier,具体可参考 文档
// .eslintrc.js
module.exports = {
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": "eslint:recommended",
"overrides": [
{
"env": {
"node": true
},
"files": [
".eslintrc.{js,cjs}"
],
"parserOptions": {
"sourceType": "script"
}
}
],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"ignorePatterns": ["temp.js", "**/vendor/*.js"],
"rules": {
}
}
//eslint.config.mjs
import globals from "globals";
import pluginJs from "@eslint/js";
export default [
{languageOptions: { globals: {...globals.browser, ...globals.node} }},
pluginJs.configs.recommended,
];
由于脚手架和以前项目都是eslint@8,所以本文只对eslint@8进行说明
2.1.1 env与globals和文件的关系
你直接在一个js文件中使用Window,会报错not defined,原因是eslint他检查出来没有定义,但我们在网页使用的时候是一定有这个东西的,所以我们在globals里面定义一个Window,这样子eslint看到以后,喔~我有这个变量,于是就不报错了,但是我们浏览器有很多变量,你能把它一个一个都加在globals里面吗,是的 有人已经做了,env的作用就是把这种环境变量统一加进去,避免我们操作
上图globals和env.browser任何一个都可以解决掉Window报错
2.1.2 rules 规则
rules就是一套规则,在eslint里面已经预设了很多,大概200多条吧,你可以创建项目的时候根据这些规则去写自己需要的(开玩笑的),首先你得清楚这些规则就是在eslint校验代码的时候用的,其次这些规则当你想集成的时候已经有人做了
- eslint:recommended 推荐配置,eslint在这些规则里面推荐了一些自己觉得好的
- eslint:all 所有配置,你的代码必须遵守我所有的规则,否则我就报错
- 第三方配置,比如你在框架创建的时候让你选择的airbnb,standard等
rules在查看的时候,里面的对钩意思就是在eslint:recommended里面存在的,小扳手的意思是eslint可以自动修复,小灯泡的意思是这些需要手动修复
2.1.3 extends继承
就如同class的继承一样,他也是继承别人的配置,比如默认配置中就是继承了eslint:recommended 配置文件,
比如我们自己安装一个第三方的配置推荐文件(都是以eslint-config开头)
# 安装第三方配置包
npm intsall eslint-config-standard
//eslintrc.js
module.exports = {
"extends": ["eslint:recommended","standard"],
"rules": {
semi: 'off'
}
}
此处的eslint-config-可以省略,如果推荐的第三方里面有一些规则你不喜欢,你可以在rules里面改为warn或者off
2.1.4 plugins插件
eslint默认只对js这些起作用,那如果是ts和vue的话,eslint本身是无能为力的,但是借助plugins就可以拓展eslint的能力,让其有在ts和vue中校验的能力(都是以eslint-plugin开头)
npm intsall eslint-plugin-vue
module.exports = {
extends: [
// add more generic rulesets here, such as:
// 'eslint:recommended',
'plugin:vue/vue3-recommended',
// 'plugin:vue/recommended' // Use this if you are using Vue.js 2.x.
],
// plugins:['vue']
rules: {
// override/add rules settings here, such as:
// 'vue/no-unused-vars': 'error'
}
}
比如上述的配置,在安装完之后就需要需要 plugins:['vue'] (可省略eslint-plugin-),引用了之后,对了,仅仅是引用,并无卵用,你插件装了,eslint有这个校验vue的能力,但是他没规则呀,所以在extends里面就需要继承这个插件里面推荐的规则集(配置文件),这样子才算完整,同时,因为你有这个extends就默认了你要用这个插件,插件这个就可以忽略掉了
2.1.5 parser解析器
有些插件使用了之后,还需要更改解析器
npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint typescript
/* eslint-env node */
module.exports = {
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
root: true,
};
为什么要更改解析器?是当你的文件默认解析器无法识别并解析成为AST树校验的时候,就需要对特殊文件指定对应的解析器
2.1.6 overrides
这个配置,普遍性和特异性 这个就是特异性,针对特定文件进行特定eslint的配置,里面的参数配置基本和外部的差不多,都有extends,plugins,rules等
需要值得注意的是里面配置文件的glob模式
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
},
extends: ['eslint:recommended'],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module',
},
rules: {
'no-console': 'warn', // 全局规则
},
overrides: [
{
files: ['*.ts'], // 针对所有 TypeScript 文件
parser: '@typescript-eslint/parser', // 使用 TypeScript 解析器
plugins: ['@typescript-eslint'], // 使用 TypeScript 插件
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended', // 引入 TypeScript 推荐规则
],
rules: {
'no-unused-vars': 'off', // 在 TypeScript 中关闭该规则
},
},
{
files: ['*.jsx'], // 针对所有 JSX 文件
rules: {
'react/prop-types': 'off', // 关闭 prop-types 规则
},
},
{
files: ['*.test.js'], // 针对所有测试文件
env: {
jest: true, // 指定测试环境
},
rules: {
'no-unused-expressions': 'off', // 关闭该规则以允许 chai 断言
},
},
],
};
- 对所有的js使用eslint:recommended配置
- 对ts使用ts配置,并更改解析器
- 对jsx和测试文件更改特定规则和指定环境
2.1.7 eslint忽略文件
2.1.7.a ignorePatterns
ignorePatterns中的 glob 模式是相对于配置文件所在的目录而言的。- 你不能在
overrides属性中使用ignorePatterns属性。 - 在
.eslintignore中定义的模式优先于配置文件的ignorePatterns属性。
2.1.7.b .eslintignore
跟.gitignore一样忽略想要忽略的文件或文件夹,注意分隔符用正斜杠,默认是忽略node_modules
2.1.8 .eslintrc/.eslintrc.js、.eslintignore 和 package.json中eslint配置的关系
{
"name": "mypackage",
"version": "0.0.1",
"eslintConfig": {
"env": {
"browser": true,
"node": true
}
},
"eslintIgnore": ["hello.js", "world.js"]
}
eslint会默认先采用.eslintrc/.eslintrc.js、.eslintignore的配置,其次才会去才去package.json的配置
[!TIP] 建议采取单独文件配置,这样package.json清爽
2.2 eslint 与 vscode eslint插件的区别
很多人容易把eslint和eslint插件搞混,其实一句话就概括了,eslint只是一个npm包,在你执行命令时候才会执行,你所看到vscode界面上的错误都是eslint插件调用你的eslint npm包,用你的配置文件.eslintrc起了一个服务,然后实时监测你的文件变化,有错我就给你标红
[!CAUTION]
注意:eslint插件的状态可以在输出,eslint中查看,如果最下面eslint状态红的时候,就说明插件运行有问题,就得需要去排查,下面的两处错误,是我从eslint@9改成eslint@8,但是配置文件还是eslint@9的配置文件报的错
2.3 prettier
2.3.1 安装prettier
npm install --save-dev --save-exact prettier
当你使用 npm install --save-dev --save-exact prettier,npm 会将依赖项版本号精确保存到 package.json,不允许自动升级到兼容的次版本或补丁版本。
2.3.2 prettier配置文件
配置文件有很多,只列举了其中一种,可以是js也可以是json
//.prettierrc
{
"trailingComma": "es5",
"tabWidth": 4,
"semi": false,
"singleQuote": true,
"overrides": [
{
"files": "*.test.js",
"options": {
"semi": true
}
},
{
"files": ["*.html", "legacy/**/*.js"],
"options": {
"tabWidth": 4
}
}
]
}
与eslint很像,也有对特殊需求的处理,当然也有对继承的处理
2.3.3 prettier忽略文件
跟.gitignore和.eslintignore一样
//.prettierignore
# Ignore artifacts:
build
coverage
# Ignore all HTML files:
**/*.html
2.3.4 prettier与eslint、stylelint起冲突
如果你使用 ESLint,请安装 eslint-config-prettier 以使 ESLint 和 Prettier 相互配合。它会关闭所有不必要的或可能与 Prettier 冲突的 ESLint 规则。Stylelint 有一个类似的配置:stylelint-config-prettier
2.3.5 prettier与.editconfig/vscode的setting起冲突
都是以.prettierrc为主
2.4 stylelint
2.4.1 stylelint安装
npm install --save-dev stylelint stylelint-config-standard
2.4.2 stylelint配置文件
//.stylelintrc{
{
"extends": ["stylelint-config-standard", "./myExtendableConfig"],
"rules": {
"alpha-value-notation": "number"
},
"overrides": [
{
"files": ["*.scss", "**/*.scss"],
"customSyntax": "postcss-scss"
},
{
"files": ["components/**/*.css", "pages/**/*.css"],
"rules": {
"alpha-value-notation": "percentage"
}
}
],
"ignoreFiles": ["**/*.js"]
}
配置文件与eslint配置文件类似,也有特殊项配置,rules参考官网,extends继承一个config
2.4.3 stylelint忽略文件
同eslint配置一样可以在配置文件中加忽略文件,也可以单独一个忽略文件
//.stylelintignore
vendor/**/*.css
3.commitlint
commitlint是校验commit信息的一个npm包
# 第一步 安装@commitlint等工具,@commitlint/config-conventional 是 Commitlint 的预定义配置,它提供了一组基于 Conventional Commits 标准的规则,用于验证提交信息是否符合规范。
npm install --save-dev @commitlint/config-conventional @commitlint/cli
# 需要一个配置文件名为commitlint.config.js,当 husky commit-msg 钩子调用的时候, npx commitlint 的时候会自动读取,从而使用规范标准校验
echo "export default { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js
那此时有人说那我就直接提交每次不是这不对,就是那不对,是的,因为如果你没学这个规范标准的话,你提交不正确就会报错,所以推荐使用commitizen
3.1 扩展 commitizen
为了使用户git提交符合规范的信息,使用的是 commitizen ,这个npm包的作用就是替代用户自己git commit -m '阿巴阿巴',生成比较规范的提交信息
# 看你自己需求,需不需要全局安装
npm install commitizen
# 如果是仅仅安装了这个包,使用npx cz的时候,会跳出下面的信息,
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch main
# Changes to be committed:
# modified: .husky/commit-msg
# modified: .husky/pre-commit
#
# Changes not staged for commit:
# deleted: .czrc
#
# Untracked files:
# .czrc11
#
# 应该是看着一脸懵逼,所以需要给commitizen一个适配器,适配器就是创建交互式信息,让你按照他的流程创建,我们因为使用的是commitlint去校验,所以我们安装符合commitlint的适配器
npm install @commitlint/cz-commitlint
安装了以后,需要一个配置文件,告诉commitzen我给你配的适配器是@commitlint/cz-commitlint,两者选择其一即可
a.在package.json中的config字段配置
"config": {
"commitizen": {
"path": "@commitlint/cz-commitlint"
}
}
b.创建一个文件.czrc
{
"path": "@commitlint/cz-commitlint"
}
此时再去运行npx cz,则得到一个符合commitlint的交互式提示,按照该提示进行操作,就不会报错了
npx cz
# ? Select the type of change that you're committing: (Use arrow keys)
# ❯ feat: A new feature
# fix: A bug fix
# docs: Documentation only changes
# style: Changes that do not affect the meaning of the code (white-space, formatting, # missing semi-colons, etc)
# refactor: A code change that neither fixes a bug nor adds a feature
# perf: A code change that improves performance
# test: Adding missing tests or correcting existing tests