08-使用Eslint和Editorconfig规范代码

对于正规的团队开发,需要规定统一的编码规范,格式化规范,以便于后期的维护。

Eslint

Eslint 是可组装的JavaScript和JSX检查工具,可以通过添加对应的插件来增加对应的javascript代码检测。

直接运行命令yarn add -D eslint eslint-loader安装。

在安装eslint相关包过程中出现如下警告

warning " > eslint-loader@2.1.2" has incorrect peer dependency "eslint@>=1.6.0 <6.0.0".

表示了我们这里安装的eslint包不适用于eslint-loader插件。具体分析请参考 外传系列-各种疑难杂症

这里我们直接卸载 eslint,安装yarn add -D eslint@5.16.0即可消除此警告。

接着我们在根目录下新增.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 babel-eslint@10.x eslint@5.x eslint-config-prettier@4.x eslint-plugin-compat@3.x eslint-plugin-import@2.x eslint-plugin-jest@22.x eslint-plugin-jsx-a11y@6.x eslint-plugin-react@7.x eslint-plugin-unicorn@6.x @typescript-eslint/eslint-plugin@1.x @typescript-eslint/parser@1.x -E -D

安装完成以后,修改 .eslintrc.js 配置

{
  "extends": "@stinkstudios/eslint-config-react-app"
}

vscode 安装对应的 eslintprettier 插件后,添加如下配置

{
    // 开启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 检测到项目根目录中的配置文件后,相关配置就会自动生效。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,265评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,078评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,852评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,408评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,445评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,772评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,921评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,688评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,130评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,467评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,617评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,276评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,882评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,740评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,967评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,315评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,486评论 2 348