@tk-shopy-test/fe-standard-lint-test v1.0.4
fe-lint
背景与原则
为简化各项目对 lint 的引入,并统一不同项目间的 lint 规则,制作此 lint 包。
核心的原则是使用简单,便于维护。最终的目的是为了提高代码质量。
因此综合考虑采取以下实现方式:
- 使用 Prettier 格式化代码,使用 stylelint 与 ESlint 控制代码质量。
- 一个 npm 包中同时提供 Prettier、stylelint、ESlint 配置,一次安装即可全部引入。
- 尽可能开启多的规则与插件以提高代码一致性与代码质量。
安装
安装 fe-lint 本身
yarn add @h/fe-lint -D
安装 peer 依赖
yarn add eslint prettier stylelint -D
安装 ESlint peer 依赖
yarn add eslint-plugin-import eslint-plugin-jest eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-taro eslint-plugin-vue eslint-plugin-vue-scoped-css @typescript-eslint/eslint-plugin @typescript-eslint/parser babel-eslint -D
安装 Prettier peer 依赖
yarn add prettier-plugin-packagejson -D
除 fe-lint 本身外,其余 peer 依赖可以根据实际需要自行选择是否安装,比如对于 React 项目则无需安装eslint-plugin-vue
。
至于为何 ESlint 与 Prettier 的 peer 依赖需要单独安装,后面的配置环节有具体解释。
VsCode 插件
针对 VsCode,推荐安装下列插件,可以提供编辑器层的代码提示与自动修复。
- dbaeumer.vscode-eslint
- esbenp.prettier-vscode
- stylelint.vscode-stylelint
如果需要开启自动修复,需要settings.json
中开启如下配置。
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.fixAll.stylelint": true
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
VsCode 的 Prettier 插件会使用默认的配置格式化代码,对于未配置 Prettier 的项目会导致代码被修改为非预期的格式。如果希望避免这一行为,可以修改 VsCode 全局设置为"editor.formatOnSave": false
,而后在希望启用 Prettier 的项目下创建.vscode/settings.json
,并修改内容如下。
{
"editor.formatOnSave": true
}
配置 Prettier
prettier 的配置非常简单,只需创建.prettierrc.js
,并写入如下内容。
module.exports = require('@h/fe-lint/prettier')
Prettier 会自动识别 Prettier 所在node_modules
下中prettier-plugin-*
作为 prettier 的插件,因此希望使用额外的 Prettier 插件只需(且必须)安装其作为(dev) 依赖即可,比如prettier-plugin-packagejson
配置 stylelint
创建stylelint.config.js
,内容如下。
module.exports = {
extends: ['@h/fe-lint/scss'],
}
如果是单纯针对 css,则使用extends: ['@h/fe-lint/css']
,less
由于内部没有使用,暂不支持。
配置 ESlint
ESlint 的配置相比之下要复杂很多,原因有二。
一是 ESlint 面临的情况更为复杂,有三个层面的变数。
- 语言层面:js、ts、jsx、tsx 需要不同的语法解析器
- 框架层面:vue、react、taro 等框架各自会有各自的 lint 插件
- 运行环境层面:build、test、src 等文件夹下的代码会分别运行于 node、jest、browser/小程序环境下,因此需要不同的 global、env 设定。
这三种变数是可以相互组合的,比如一个 vue 文件,可能是 ts 的,也可能是 js 的,或 test 目录下可能存在 tsx 文件,也可能存在 js 文件,因此需要提供针对多种情况的配置。
二是各种变数、插件导致有各种流行的配置集合,规则数量也远远多于 stylelint 与 Prettier,因此单就工作量而论复杂性也大大增加。
此外,ESlint 还有一点与 stylelint 不同的地方,即 ESlint 中配置plugins
字段必须为 npm 包名而非是绝对路径,这导致了 ESlint 的 plugin 必须单独安装,而无法通过require.resolve
作为 fe-lint 的依赖存在。
这一设定的一个原因是为了避免不同的配置使用了同名但不同版本的插件,更多可以参见相关讨论
因此,为了解决上述的问题,ESlint 的相关配置按照如下原则组织:
- 尽可能使用 React、Vue、ESlint 等官方维护的 recommend 配置。相比自行配置所有的规则详情,使用官方维护配置可以降低更新成本,同时代码更轻量方便后人阅读。
- 开箱即用式提供常见情况下的配置,如
react-ts
是适合于使用 ts 的 React 项目。
比如对于一个典型的 build 目录下是构建脚本,src 下是源代码,test 下是使用 jest 编写的测试用例的项目,.eslintrc.js
内容如下。
使用 require.resolve
是因为 ESlint 要求共享的配置必须命名为 eslint-config 形式,而 fe-lint 由于并非是单纯的 eslint 配置,所以未遵循这已要求。
module.exports = {
extends: [require.resolve('@h/fe-lint/js.js')],
overrides: [
{
files: ['./build'],
extends: [require.resolve('@h/fe-lint/node.js')],
},
{
files: ['./src'],
extends: [require.resolve('@h/fe-lint/config-suitable.js')],
},
{
files: ['./test'],
extends: [
require.resolve('@h/fe-lint/config-suitable.js'),
require.resolve('@h/fe-lint/jest.js'),
],
},
],
}
其中config-suitable
有如下选择,即内置了语言与框架的所有组合。
js.js
:最基础的 js 规则ts.js
:最基础的 ts 规则vue-js.js
:针对使用 js 的 vue 文件的规则vue-ts.js
:针对使用 ts 的 vue 文件的规则react-js.js
:针对使用 jsx 的 react 文件的规则react-ts.js
:针对使用 tsx 的 react 文件的规则taro-ts.js
:针对使用 tsx 的 taro 的文件规则(目前 taro 小程序没有 ts 版的,故未提供 js 规则。且仅提供针对 taro2.x 版本的规则)
至于 jest、node 等环境的组合则可以单独叠加
比如对于使用 ts 的 react 项目,其配置如下:
module.exports = {
// 基础都是js
extends: ['@h/fe-lint/js.js'],
overrides: [
// src下的ts使用ts相关的配置
{
files: ['./src/**/*.ts'],
extends: [require.resolve('@h/fe-lint/ts.js')],
},
// src下的tsx使用tsx相关的配置
{
files: ['./src/**/*.tsx'],
extends: [require.resolve('@h/fe-lint/react-ts.js')],
},
// test下的ts使用ts叠加jest相关配置
{
files: ['./test/**/*.ts'],
extends: [
require.resolve('@h/fe-lint/jest.js'),
require.resolve('@h/fe-lint/ts.js'),
],
},
// test下的ts使用tsx叠加jest相关配置
{
files: ['./test/**/*.tsx'],
extends: [
require.resolve('@h/fe-lint/jest.js'),
require.resolve('@h/fe-lint/react-ts.js'),
],
},
],
}
其余项目可仿照上例配置。
对于 ts 项目,如果需要指定parserOptions
中的project
字段,直接添加对应配置即可。
更多例子可以参考demo目录。
ESlint 与 alias
项目中常常会用到 alias,比如用@/
表示<project-root>/src/
。如果需要 alias 可以被顺利识别与编译,需要下面几个方面的配置。
- webpack、ts 等构建工具中的配置。否则会因为无法识别 alias 导致构建报错
- tsconfig.json、jsconfig.json 中的配置。否则会因为 vscode 不识别 alias 导致代码补全问题
- Eslint 的配置。否则会出现
eslint-plugin-import
无法识别 alias 的报错
其中eslint-plugin-import
可以识别其他文件中的 alias 配置,详见Resolvers。
比如对于 ts 项目,eslintrc.js
中添加如下配置即可。
settings: {
'import/resolver': {
typescript: {
directory: './',
},
},
}
同时注意需要添加依赖eslint-import-resolver-typescript
。
disable 与 ignore
ignore
- 对于 Prettier,使用
.prettierignore
,语法与 gitignore 相同 - 对于 ESlint,使用
.eslintignore
,语法也 gitignore 相同 - 对于 stylelint,需要使用
ignoreFiles
字段,参考相关文档。stylelint 会默认忽略 node_modules,且样式文件通常只在 src 下,因此一般不需要配置 ignore
disable
- stylelint 的 disable 语法与 ESlint 的语法基本相同,需要注意的是在 vue 组件下的 csss 中
stylelint-disable-next-line
只在/**/
的注释中才能生效。 - ESlint 除去通常的用法外,还可以使用逗号分隔多条 disable 的规则。7.0 之后,ESlint 支持使用
--
语法做解释说明,比如:// eslint-disable-next-line none-console --这里log一下数据便于排查
- Prettier 使用
prettier-ignore
,但针对不同类型的文件会有变体,详细可参考文档。注意 Prettier 的 ignore 为 ignore 其后的第一个语法节点。
CLI
三者的 CLI 使用示例如下,可根据项目实际情况做对应调整。
{
"prettier": "prettier --check .",
"prettier:fix": "prettier --write .",
"lint:es": "eslint --ext .js,.vue ./",
"lint:es-fix": "npm run lint:es -- --fix",
"lint:style": "stylelint 'src/**/*.scss' --syntax scss && stylelint 'src/**/*.vue'",
"lint:style-fix": "stylelint 'src/**/*.scss' --syntax scss --fix && stylelint 'src/**/*.vue' --fix"
}