# 🔌 ESLint x Plugins

上一篇在配置 ESLint x TypeScript 时,我们发现了 Parser 和 Plugin 的规律,下面来聊聊一些常见的 Parser 和 Plugin。

# ESLint x Babel

在第一篇文章里就说了,可以通过 env 来设定 ESLint 的默认 ECMAScript parser 的版本,所以 ESLint 其实是自带有 parser 的,但是它只支持 最新版的 ECMAScript 标准 (opens new window)。

而 JavaScript 依然在不断发展,时不时又出一些新的 API 或者提案,对于要尝鲜的开发者,ESLint 的 Parser 就解析不动 .js 了,因此,我们需要 @babel/eslint-parser (opens new window)。

npm i -D @babel/core @babel/eslint-parser

然后添加 .babelrc.js,在里面写项目的 babel 规则,这里按你自己需求来就好了,我就不写啦。

然后在 overrides 里新增对 .js 的处理:

module.exports = {
  env: {
    // 支持浏览器环境
    browser: true,
    // 识别 CommonJS
    node: true,
    // 识别 ES 的代码,使用 ECMAScript 2021 自动设置 ecmaVersion parser 为 12,
    es2021: true,
  },
  extends: [
    "eslint:recommended", // eslint 自己的推荐规则,最佳实践最小集
    "plugin:prettier/recommended", // 禁用 eslint 关于代码的风格的规则,使用 prettier 的风格
  ],
  overrides: [
    // 处理 JS 文件
    {
      files: ["**/*.{js,jsx}"], // 只处理 js 和 jsx 文件
      parser: "@babel/eslint-parser", // 使用 babel 来解析 js 文件
      parserOptions: {
        sourceType: "module", // 支持 import/export
        allowImportExportEverywhere: false,
        ecmaFeatures: {
          globalReturn: false,
        },
      },
    },
    // 处理 TS 文件
    {
      files: ["**/*.{ts,tsx}"], // 只处理 ts 和 js 文件
      parser: "@typescript-eslint/parser", // 能看懂 TypeScript
      parserOptions: {
        project: ["./tsconfig.json"], // 告诉 eslint:tsconfig 在哪
      },
      extends: [
        // typescript-eslint 的推荐规则,只是这些最佳规则都是针对 TS 的
        "plugin:@typescript-eslint/recommended",
        // tsconfig.json 里 Type Checking 的推荐规则
        "plugin:@typescript-eslint/recommended-requiring-type-checking",
      ],
      plugins: [
        // 使用 typescript x eslint 的插件
        "@typescript-eslint",
      ],
    },
  ],
};

# ESLint x React

解析 React 文件主要有两大难题:

  • 不识别 import React from 'react',会报 React is not used
  • 不识别 .jsx, .tsx 文件

如果你的项目是 React + TypeScript,那么要在 tsconfig.json 里添加对 JSX 的支持:

{
  ...
  "jsx": "react"
}

然后在 overrides 里也添加对 .js 和 .jsx 的解析:

module.exports = {
  overrides: [
    {
      files: ["**/*.{jsx,js,ts,tsx}"],
      ...ESLint x TypeScript 配置
    }
  ]
}

因为 ESLint 这里会 TypeScript 的 parser 结合 tsconfig.json 来解析 .js 和 .jsx,所以 ESLint 是能看懂 .jsx 的内容的。

那如果项目是 React + JavaScript 呢?或者我就要分开处理 TypeScript 和 JavaScript 呢?我们难道要用 React Parser 么?No!我们需要的是 ESLint x React 的插件!个人理解 JSX 更属于 JavaScript 的一种特性,而不是语法类型,所以要用 Plugin。

遵循刚刚说的规律,我们安装 eslint-plugin-react (opens new window):

npm i D eslint-plugin-react

最后只需继承它即可,注意这里的 extends 大部分时候都可以是 plugin 的缩写版本:

"extends": [
  "eslint:recommended",
  "plugin:react/recommended"
]

# ESLint x Vue

Vue 和 React 同理,它只需要一个 eslint-plugin-vue (opens new window):

npm i -D eslint-plugin-vue

我们依然可以在 overrides 中新增一条只针对 .vue 文件的配置:

overrides: [
  // 处理 vue 文件
  {
    files: ["**/*.vue"], // 只处理 vue 文件
    extends: ["plugin:vue/vue3-recommended"], // 使用 vue3 的推荐规则
  }
]

这样就可以对所有 .vue 文件执行 eslint '**/*.vue' --fix 了。

# extends 和 plugins 的区别

不知道你有没有在刚刚配置 eslint 的时候,有两个配置项一直很让人迷惑:extends 以及 plugins。

举个例子,我们要配置 eslint x typescript,可以看到官网有这样的配置:

module.exports = {
  root: true,
  parser: '@typescript-eslint/parser',
  plugins: [
    '@typescript-eslint',
  ],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
  ],
};

神奇的是,当你去掉 plugins 之后发现 eslint 依然可以正常工作。更神奇的是,只要你写了 extends,那么连 parser 也可以不用加,要知道没有指定 parser 选项,eslint 可看不懂你的 TypeScript 文件。

所以说,到底是 plugins 加上了 TypeScript 的能力还是 extends 加上了 TypeScript 的规则呢?真让人头大,直到终于有一天受不了了,翻找了一下网上的资料发现了这个帖子 (opens new window)。

先来说结论吧:每个 plugins 只是开启了这个插件,而 extends 则会继承别人写好的一份 .eslintrc 的配置,这份配置不仅仅包括了 rules 还有 parser,plugins 之类的东西。

所以回到问题,为什么在继承了 plugin:@typescript-eslint/recommended 之后就可以不写 plugins 和 parser 呢?因为别人已经把配置都放在 recommended 这份配置表里了,这样对使用的人来说,就可以少写很多配置项了。

也就是说,下面两份配置是等价的:

module.exports = {
  parser: "@typescript-eslint/parser",
  parserOptions: { sourceType: "module" },
  plugins: ["@typescript-eslint"],
  extends: [],
  rules: {
    "@typescript-eslint/explicit-function-return-type": [
      "error",
      {
        allowExpressions: true
      }
    ]
  }
}

以及

module.exports = {
  plugins: [],
  extends: ["plugin:@typescript-eslint/recommended"],
  rules: {
    "@typescript-eslint/explicit-function-return-type": [
      "error",
      {
        allowExpressions: true
      }
    ]
  }
}

对于第一份配置:

  • 需要手动添加 parser, parserOptions, plugins
  • 只开启了 @typescript-eslint/explicit-function-return-type 一个规则

对于第二份配置:

  • plugin:@typescript-eslint/recommended 自动添加了 parser, parserOptions, plugins
  • 一些推荐的 TypeScript ESLint 规则也自动加上了
  • 只对 @typescript-eslint/explicit-function-return-type 这个规则进行自定义配置

# 考考你

看到这,你的 .eslintrc.js 应该已经写了不少代码了,当然相信你也能慢慢找到 eslint, plugin, config, prettier, parser 这些关键词之间排列组合的一些规律了。

不妨来考考你:

  • 我要用 XXX 公司的 ESLint 规则集,应该找哪个名字的 NPM 包?
  • 我要解析 YYY 语法,应该搜哪个 NPM 包呢?
  • 要屏蔽 XXLint 工具和 Prettier 冲突的规则,应该用哪个 NPM 包?
  • 要让处理 .xxx 后缀的文件,应该用到哪些 NPM 包呢?

如果你对上面的问题都能做到心中有数,那配置 StyleLint (opens new window) 就再简单不过了。实际上无论是哪个 xxlint 他们的 NPM 命名规律都是非常类似的。话不多出,马上开始学习下一章吧~

Last Updated: 4/13/2022, 7:24:23 PM