对于正规的团队开发,需要规定统一的编码规范,格式化规范,以便于后期的维护。
Eslint
Eslint 是可组装的JavaScript和JSX检查工具,可以通过添加对应的插件来增加对应的javascript代码检测。
直接运行命令yarn add -D eslint eslint-loader
安装。
在安装eslint相关包过程中出现如下警告
warning " > [email protected]" has incorrect peer dependency "eslint@>=1.6.0 <6.0.0".
表示了我们这里安装的eslint包不适用于eslint-loader插件。具体分析请参考 外传系列-各种疑难杂症。
这里我们直接卸载 eslint,安装yarn add -D [email protected]
即可消除此警告。
接着我们在根目录下新增.eslintrc.js 配置eslint的检测规则。.eslintrc.js包括以下配置项:
- rules 启用的规则及其各自的错误级别,详细可以参考 eslint规则。
- parser 配置解释器,默认为 Espree,我们也可以配置 babel-eslint 作为解释器。
- parserOptions 解析器选项,能帮助 ESLint 确定什么是解析错误。
- env 指定想启用的环境,并设置它们为 true。
- globals 定义全局变量,这样源文件中使用的全局变量就不会发出警告。
- plugins 配置第三方插件,插件名称可以省略 eslint-plugin- 前缀。
- settings 添加共享设置,提供给每一个将被执行的规则。
- root 设置为 true,停止在父级目录中查找。
- extends 可以从基础配置中继承已启用的规则。
- overrides 可以实现精细的配置,比如,如果同一个目录下的文件需要有不同的配置。
大概就是如下图所示这种感觉了。要深入了解请参考 官方文档
module.exports = {
// 停止在父级目录中查找
"root": true,
// 启用一系列核心规则
"extends": "eslint:recommended",
// 启用的规则及其各自的错误级别
"rules": {
"semi": ["error", "always"],
"quotes": "error",
// 启用插件专用的规则
"example-plugin/eqeqeq": "off"
},
// 解析器选项
"parserOptions": {
// ECMAScript 版本
"ecmaVersion": 6,
// 设置为 "script" (默认) 或 "module"(如果你的代码是 ECMAScript 模块)
"sourceType": "module",
// 使用的额外的语言特性
"ecmaFeatures": {
// 启用 JSX
"jsx": true
}
},
// 一个对Babel解析器的包装,使其能够与 ESLint 兼容
"parser": "babel-eslint",
// 全局变量
"globals": {
"document": false,
"window": false,
"HTMLInputElement": false,
"HTMLDivElement": false,
"localStorage": true
},
// 指定想启用的环境
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"jest": true,
"node": true,
// 指定插件专用环境
"example-plugin/browser": true
},
// 配置插件
"plugins": [
"example-plugin"
],
// 匹配特定的 glob 模式的文件
overrides: {
// 匹配所有.ts .tsx 文件
files: ['**/*.ts', '**/*.tsx'],
// 指定解析器
parser: '@typescript-eslint/parser',
// 指定解析器选项
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: {
jsx: true,
}
}
}
}
自己重新定义eslint 的配置太累,我们可以以共享的配置 为基础,来扩展我们自己的配置,这样最省力,不干重复造轮子的事情。
本来想直接使用create react app 脚手架所自带的eslint-config-react-app,网上找了下发现这个还不错,打包了格式化插件 prettier,又省事了。
@stinkstudios/eslint-config-react-app
按照指南执行如下命令
yarn add @stinkstudios/eslint-config-react-app [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] @typescript-eslint/[email protected] @typescript-eslint/[email protected] -E -D
安装完成以后,修改 .eslintrc.js 配置
{
"extends": "@stinkstudios/eslint-config-react-app"
}
vscode 安装对应的 eslint 和 prettier 插件后,添加如下配置
{
// 开启eslint对javascript文件的检查
"eslint.enable": true,
// 开启保存文件时是否启用eslint规则自动修改
"eslint.autoFixOnSave": true,
// 配置eslint验证的语言
"eslint.validate": [
"javascript",
"javascriptreact",
{
"language": "typescript",
"autoFix": true
},
{
"language": "typescriptreact",
"autoFix": true
}
],
// 关闭保存时格式化文件
"editor.formatOnSave": false,
// 开启js文件自动保存格式化
"[javascript]": {
"editor.formatOnSave": true
},
// 开启jsx文件自动保存格式化
"[javascriptreact]": {
"editor.formatOnSave": true
},
// 开启ts文件自动保存格式化
"[typescript]": {
"editor.formatOnSave": true
},
// 开启tsx文件自动保存格式化
"[typescriptreact]": {
"editor.formatOnSave": true
},
// 开启prettier使用eslint的代码格式进行校验
"prettier.eslintIntegration": true
}
这样打开相应的源代码,会出现对应的警告和错误提示
如果我们想再编译时执行检查,需要另外安装
yarn add -D eslint-loader
并在webpack中添加对应的配置
// 配置项目处理的不同文件及模块
module: {
rules: [
{
test: /\.(ts|tsx|js|jsx)$/,
exclude: /node_modules/,
include: path.resolve(__dirname, "src"),
use: {
loader: 'babel-loader'
}
},
{
enforce: 'pre',
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
include: path.resolve(__dirname, "src"),
loader: 'eslint-loader',
},
]
}
enforce: 'pre'
保证了,eslint 检查的源代码是在 babel 编译前的代码文件。再执行编译后,控制台输出需要解决的错误与警告。
yarn run v1.16.0
$ webpack --config webpack.prod.js
Hash: 3b26a80a14e418556fee
Version: webpack 4.35.0
Time: 18915ms
Built at: 2019-07-02 5:05:38 PM
12 assets
Entrypoint main = manifest.main.f8d73da419e4743861f3.js manifest.main.f8d73da419e4743861f3.js.map verdor.40b18c99978b06ccfb59.js verdor.40b18c99978b06ccfb59.js.map main.2d6862e337695d1c7c2d.js main.2d6862e337695d1c7c2d.js.map
[5] ./src/constants.ts 348 bytes {1} [built]
[6] ./node_modules/history/esm/history.js + 2 modules 30.6 KiB {0} [built]
| 3 modules
[11] ./node_modules/react-router/esm/react-router.js + 1 modules 27.7 KiB {0} [built]
| 2 modules
[30] ./node_modules/react-redux/es/index.js + 15 modules 28.8 KiB {0} [built]
| 16 modules
[33] (webpack)/buildin/global.js 472 bytes {0} [built]
[39] ./node_modules/connected-react-router/esm/index.js + 5 modules 13.3 KiB {0} [built]
| 6 modules
[109] (webpack)/buildin/harmony-module.js 573 bytes {0} [built]
[131] ./src/index.tsx + 7 modules 14 KiB {1} [built] [7 errors]
| ./src/index.tsx 187 bytes [built]
| ./src/containers/App.tsx 4.01 KiB [built] [1 error]
| ./src/store/configureStore.ts 915 bytes [built] [1 error]
| ./src/containers/Top.tsx 2.72 KiB [built] [1 error]
| ./src/containers/ErrorBoundary.tsx 3.3 KiB [built] [1 error]
| ./src/reducers/novel.ts 1.67 KiB [built] [1 error]
| ./src/middleware/index.ts 503 bytes [built] [1 error]
| + 1 hidden module
[134] ./node_modules/redux-actions/es/handleActions.js + 13 modules 7.25 KiB {0} [built]
| 14 modules
[135] ./node_modules/redux-actions/es/createAction.js + 1 modules 1.43 KiB {0} [built]
| 2 modules
[136] ./src/containers/About.tsx 141 bytes {3} [built] [1 error]
[137] ./src/containers/MaterialUI.tsx 2.76 KiB {4} [built] [1 error]
[138] ./src/containers/NovelContainer.tsx + 4 modules 5.52 KiB {5} [built] [1 warning] [4 errors]
| ./src/containers/NovelContainer.tsx 1.1 KiB [built] [1 error]
| ./src/actions/novel.ts 793 bytes [built] [1 warning]
| ./src/services/novelapi.ts 182 bytes [built] [1 error]
| ./src/services/api.ts 2.96 KiB [built] [1 error]
| + 1 hidden module
+ 142 hidden modules
解释一下下面几个插件的作用:
- eslint-plugin-compat 根据 browserslist 的配置提示浏览器是否兼容。
- eslint-plugin-import 支持 ES2015+ (ES6+) import/export语法,并防止文件路径和导入名称错误拼写的问题。
- eslint-plugin-jest eslint 用来支持jest的插件。
- eslint-plugin-jsx-a11y 基于JSX元素的可访问性规则的静态AST检查器。
- eslint-plugin-react 用于react的eslint 规则插件。
- eslint-plugin-unicorn 使用 xo 打包的一些默认规则。
- eslint-config-prettier 将 prettier 作为 eslint d的规则来报告相应的问题。
在此基础上我们可以扩展下我们自己需要的规则,添加额外的插件。例如支持检查 React 16.8 的 Hook 特性的插件。
安装yarn add -D eslint-plugin-react-hooks
插件,添加插件定义的规则。
module.exports = {
// 继承已有的共享配置
"extends": "@stinkstudios/eslint-config-react-app",
// 启用的规则及其各自的错误级别 0-off 1-warn 2-error
"rules": {
// 不禁用console
'no-console': 0,
// 防止在React组件定义中丢失props验证
"react/prop-types": 0,
// 关闭 ox 规则中的文件名小写
'unicorn/filename-case': 0,
// 遵循官方Hook规则的验证
'react-hooks/exhaustive-deps': 1,
'react-hooks/rules-of-hooks': 2,
},
// 配置插件
"plugins": [
"react-hooks"
],
}
如此我们可以通过Eslint来完成项目中的静态检查。
EditorConfig
editorconfig 保证了我们在不同的环境,使用不用的编辑器都有统一的规范。比如在 window 上默认换行使用 CRLF, 而在 mac 上的换行风格是 IF ; 有的编辑器默认缩进使用 Tab, 而有的编辑器使用 Space 等。
vscode 环境需要安装 EditorConfig for VS Code 插件,并在根目录下增加配置文件 .editorconfig
# 标记此配置文件为最顶层
root = true
# 匹配所有文件
[*]
# 缩进格式 空格
indent_style = space
# 缩进格式字符大小
indent_size = 2
# 换行格式
end_of_line = lf
# 字符编码
charset = utf-8
# 去除每行末尾多余空格
trim_trailing_whitespace = true
# 在代码末尾添加新行
insert_final_newline = true
当然我们也可以给不同的文件,赋予特有的规范,只要新增一个匹配加对应规则即可。比如如下所示给所有后缀名为 ts 和 tsx 的文件指定缩进格式为4个空格。
[*.{ts, tsx}]
indent_style = space
indent_size = 4
当插件 EditorConfig for VS Code 检测到项目根目录中的配置文件后,相关配置就会自动生效。