ESLint&Prettier学习资源+问答

292 阅读7分钟

以下是我在学习ESLint和Prettier过程中觉得优质的学习资源(感谢这些作者的倾力分享)和一些通过这些资料得到解答的困惑的汇总

啰里八嗦一下

我原本的计划是想写一篇ESLint和Prettier的实践教程,但是我看社区里类似的文章已经讲的很全面了。因此我决定换一种形式:汇总我在实践中遇到的问题,希望能够帮助到有类似困惑的同学。

原文内容的广度远超我自己罗列的那些问题,有兴趣的同学可以先看看我的解答,然后点进链接学习了解更加详细的内容,如果你也有自己的问题,欢迎在评论中提出来。对于文中出现的错误,欢迎大家指正。

问题汇总:

铺垫部分

  1. ESLint的工作原理是什么?——ESLint工作原理探讨
  2. ESLint为什么能从各种Lint工具中突出重围?——深入理解 ESlint(Lint工具简史部分)
  3. Prettier和ESlint的区别是什么?—— Why You Should Use ESLint, Prettier & EditorConfig
  4. ESLint也能处理代码格式(code-formating)规则,为什么还需要Prettier——Prettier看这一篇就行了

实践部分

  1. 我的项目是TypeScript+React,我是否需要特殊的配置? —— Setting up ESLint to work with TypeScript
  2. extends和plugins的区别是什么?为什么有的extends前面会带上"plugin:"前缀?eslint-config-xxx和eslint-plugin-xxx又有什么区别?——ESLint工作原理探讨

铺垫

1. ESLint的工作原理是什么?——ESLint工作原理探讨

Lint工具需要根据规则对我们的代码进行分析、规范,则势必要将我们代码解析成抽象语法树(AST),再根据AST判断我们的代码是否符合Linter的规则。至于AST是什么,我们可以打开AST explorer,他会给你更直观的感受。

ast

右侧的Tree就是左侧源代码的到的AST结果。

以规则max-params(强制函数定义中最多允许的参数数量)为例,通过遍历所有FunctionDeclaration的params(上图蓝框),获取它们的长度,我们就能判断出源代码是否符合max-params这条规则。

但AST仅仅是第一步,并非所有规则都能仅通过AST就得出结果,因为我们知道代码还会有循环,条件判断,这会涉及到ESLint的Code Path Analysis,本文暂不涉及,想了解的同学可以戳原文(超级棒)

2. ESLint为什么能从各种Lint工具中突出重围?——深入理解 ESlint(Lint工具简史部分)

很多大牛都说过,在学习一门技术前,可以先去了解它们的出现时机、历史背景,这会让我们更加理解这门技术,增强你对这门技术的画面感,很多技术上的解决方案也会变得合情合理。

这一部分在深入理解 ESlintLint工具简史部分讲得和详细(快戳原文),在此不多赘述。关键就四个字,可扩展性。

3. Prettier和ESlint的区别是什么?—— Why You Should Use ESLint, Prettier & EditorConfig

这个问题仅从校验规则范围的角度回答。以下为原文。

To answer the first question, one should keep in mind that linters ultimately have two categories of rules:

  • Formatting rules: Rules that prevent inconsistent and ugly looking code (eg: max-len, no-mixed-spaces-and-tabs, keyword-spacing, comma-style…)
  • Code-quality rules: Rules that prevent useless or error making code (eg no-unused-vars, no-extra-bind, no-implicit-globals, prefer-promise-reject-errors…)

简单翻译一下:

Linter的规则分为两类:

  1. 代码格式(code-formating)规则:使代码变得Prettier

    • max-len:强制一行的最大长度
    • comma-style:强制使用一致的逗号风格
    • ...
  2. 代码质量(code-quality)规则:一定程度上避免无用的和错误的代码

    ESLint对这两类规则都能处理,但是Prettier只能够处理第一种代码格式(code-formating)规则。

4. ESLint也能处理代码格式(code-formating)规则,为什么还需要Prettier——Prettier看这一篇就行了

Redux的作者Dan Abramov自己的博客中的这样一段话很好地总结了Prettier的存在意义:

Prettier 然后忘掉 “风格”。如果有别的工具能为你自动修复,你完全不需要一个工具告诉你得在这加一个空格。用 linter 找 bug,而不是做 代 码 美 学

而Prettier对自己的定义也是如此——Prettier is an opinionated code formatter,opinionated的意思在**Prettier看这一篇就行了**中讲的很清楚,简而言之就是,关于代码格式的问题,我不要你们觉得,我(Prettier本我)要我觉得,你们不需要在意代码风格,这件事我会帮你自动修复。而这种ESLint专注于代码质量相关的提示,代码格式问题Prettier自动格式化的模式,我认为是很合理的。

实践

1. 我的项目是TypeScript+React,是否需要特殊的配置? —— Setting up ESLint to work with TypeScript

铺垫-1中我们提到了ESLint是通过将源代码转化成AST来进行代码检测的,而ESLint中的parser配置项就是用于指定将源代码转化成AST的解析器

常见的解析器有这样三个:

  1. espree:ESLint默认解析器;

  2. babel-eslint:支持实验性,非标准的语法;

  3. @typescript-eslint/parser:typescript语法的解析器。

    因此,假如我们要在项目中使用typescript,就需要将parser配置为@typescript-eslint/parser

    {  
      "parser": "@typescript-eslint/parser" 
    }
    

其次,就是ESLint对于React的配置,通过eslint-plugin-react就可以实现,文档中有很详细的描述,在此不多赘述。但在写文章的这个时候,我想到:为什么React不需要另外的parser来解析,毕竟react需要解析JSX。但又想到在parserOptions.ecmaFeatures配置中,我们会将jsx设置为true。而且在eslint-plugin-react源代码中,也是将jsx设置为true。因此我猜测(仅仅为猜测),ESLint可以通过将jsx设置为true,支持jsx语法,而eslint-plugin-react就能在此基础上创建的react的第三方规则了。

{
 "parserOptions": {
   "ecmaFeatures": {
     "jsx": true
   }
 }
}

2. extends和plugins的区别是什么?为什么有的extends前面会带上"plugin:"前缀?eslint-config-xxx和eslint-plugin-xxx又有什么区别?——ESLint工作原理探讨

首先,我们来看两份配置:

第一份:

{
  "extends": [
    "plugin:react/recommended"
  ]
}

第二份:

{
  "plugins": [
    "react"
  ]
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    }
  }
  "rules":{
     // 所有eslint-plugin-react/recommended
    "react/jsx-uses-react": "error",
    "react/jsx-uses-vars": "error",
    ...
  }
}

这两份配置有什么区别吗?答案是,没有区别。"plugin:react/recommended"就代表了其他所有的配置,我们可以从eslint-plugin-react源码得到证明。

这个问题看起来有些幼稚,但是它却暴露了我自己对extends这个字段理解上的误区:我最开始的理解是extends代表的是规则(rule)的集合,像parserOptionsplugins这些字段并不包含在extends中,而正确的理解应该extends是eslint配置的预设,而非规则(rule)的集合

现在,我们再来理解前缀**"plugin:"**,plugin的功能可以总结为两个方面:

1. 输出eslint配置的预设,也就是一个"extend"

因此例如plugin:react/recommended,就相当于eslint-plugin-react提供的"recommended"预设,同样在eslint-plugin-react源码我们能找到对应的recommended预设,还有默认的"all"预设。

2. 创建第三方规则

以React为例,React的ESLint规则在ESLint基础规则中是没有的。这时,我们就需要**开发一个ESLint插件**,来创建属于我们自己的规则。

第三个问题是eslint-config-xxx和eslint-plugin-xxx有什么区别。我们可以理解成eslint-config-xxx只拥有eslint-plugin-xxx的功能1,但是没有功能2。

总结一下上面提到的三个问题:

  1. extend不是eslint的rule的集合,而是eslint配置的预设,plugin则是用于提供预设和创建第三方规则。

  2. plugin:react前缀表示这个extend(预设)是由eslint-plugin-react输出的

  3. eslint-plugin-xxx和eslint-config-xxx的区别在于前者可以定义第三方规则,但是后者则仅仅是预设而已

突然结束😬