🔌 ESLint x Plugins

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

ESLint x Babel

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

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

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

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

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

  1. module.exports = {
  2. env: {
  3. // 支持浏览器环境
  4. browser: true,
  5. // 识别 CommonJS
  6. node: true,
  7. // 识别 ES 的代码,使用 ECMAScript 2021 自动设置 ecmaVersion parser 为 12,
  8. es2021: true,
  9. },
  10. extends: [
  11. "eslint:recommended", // eslint 自己的推荐规则,最佳实践最小集
  12. "plugin:prettier/recommended", // 禁用 eslint 关于代码的风格的规则,使用 prettier 的风格
  13. ],
  14. overrides: [
  15. // 处理 JS 文件
  16. {
  17. files: ["**/*.{js,jsx}"], // 只处理 js 和 jsx 文件
  18. parser: "@babel/eslint-parser", // 使用 babel 来解析 js 文件
  19. parserOptions: {
  20. sourceType: "module", // 支持 import/export
  21. allowImportExportEverywhere: false,
  22. ecmaFeatures: {
  23. globalReturn: false,
  24. },
  25. },
  26. },
  27. // 处理 TS 文件
  28. {
  29. files: ["**/*.{ts,tsx}"], // 只处理 ts 和 js 文件
  30. parser: "@typescript-eslint/parser", // 能看懂 TypeScript
  31. parserOptions: {
  32. project: ["./tsconfig.json"], // 告诉 eslint:tsconfig 在哪
  33. },
  34. extends: [
  35. // typescript-eslint 的推荐规则,只是这些最佳规则都是针对 TS 的
  36. "plugin:@typescript-eslint/recommended",
  37. // tsconfig.json 里 Type Checking 的推荐规则
  38. "plugin:@typescript-eslint/recommended-requiring-type-checking",
  39. ],
  40. plugins: [
  41. // 使用 typescript x eslint 的插件
  42. "@typescript-eslint",
  43. ],
  44. },
  45. ],
  46. };

ESLint x React

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

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

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

  1. {
  2. ...
  3. "jsx": "react"
  4. }

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

  1. module.exports = {
  2. overrides: [
  3. {
  4. files: ["**/*.{jsx,js,ts,tsx}"],
  5. ...ESLint x TypeScript 配置
  6. }
  7. ]
  8. }

因为 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

  1. npm i D eslint-plugin-react

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

  1. "extends": [
  2. "eslint:recommended",
  3. "plugin:react/recommended"
  4. ]

ESLint x Vue

Vue 和 React 同理,它只需要一个 eslint-plugin-vue

  1. npm i -D eslint-plugin-vue

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

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

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

extendsplugins 的区别

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

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

  1. module.exports = {
  2. root: true,
  3. parser: '@typescript-eslint/parser',
  4. plugins: [
  5. '@typescript-eslint',
  6. ],
  7. extends: [
  8. 'eslint:recommended',
  9. 'plugin:@typescript-eslint/recommended',
  10. ],
  11. };

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

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

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

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

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

  1. module.exports = {
  2. parser: "@typescript-eslint/parser",
  3. parserOptions: { sourceType: "module" },
  4. plugins: ["@typescript-eslint"],
  5. extends: [],
  6. rules: {
  7. "@typescript-eslint/explicit-function-return-type": [
  8. "error",
  9. {
  10. allowExpressions: true
  11. }
  12. ]
  13. }
  14. }

以及

  1. module.exports = {
  2. plugins: [],
  3. extends: ["plugin:@typescript-eslint/recommended"],
  4. rules: {
  5. "@typescript-eslint/explicit-function-return-type": [
  6. "error",
  7. {
  8. allowExpressions: true
  9. }
  10. ]
  11. }
  12. }

对于第一份配置:

  • 需要手动添加 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 就再简单不过了。实际上无论是哪个 xxlint 他们的 NPM 命名规律都是非常类似的。话不多出,马上开始学习下一章吧~