eslint+prettier 调研

2,505 阅读5分钟

开篇

对于前端开发来说,如何统一代码风格一直是我们开发过程中的一大痛点。

目前业界比较流行 eslint + prettier 搭配使用来解决这个问题。

我从很久以前就开始用eslint了, eslint 提供了不亚于静态语言的编写时检查,来帮助我们提前发现代码中的bug。再搭配vscodeeslint.autoFixOnSave 食用,极大提升了开发体验。

但是对于代码格式化来说,eslint就显得有点吃力了。

比如很多时候,我们需要拷贝别人的代码,然后发现拷贝来的代码有一行过长了。对于有强迫症的我来说,就只能一点点换行了,很影响心情。

此时,就是prettier 的用武之地了。代码格式化,保存,开心。

探索

如果真的有这么美好就好了,可惜,现实很骨感。

首先,就是这两个工具搭配起来造成的冲突问题。

举个例子,这两个工具都可以规定引号是单是双。如果eslint 要双引号,prettier 却要单引号。

就会造成这种纠结情况:一格式化,代码变成单引号,一开开心心保存又变成回了双引号,无限循环。

那我们如何解决这个问题呢?

最直观的做法是,我们统一他们的配置不就行了吗?让eslintprettier 都是单引号。

没错,这是个办法。

但是,我们需要在两个配置文件里配置两次相同的规则,这未免有点不DRY,对于追求完美的我来说,这是不能接受的。

此时,prettier站了出来,提供了一个插件 eslint-config-prettier,它做了这么一件事,凡是跟我冲突的规则,都给你禁用掉。使用了这个插件,对于那些会冲突的规则,我们就只需要在.prettierrc.js中配置一份就行了,因为eslint你配置了也不生效。很好,这很霸道。

但是,还是有问题。我们看看prettier官网怎么说的,在它的Philosophy中,第一句话是这么写的:

Prettier has a few options because of history. But we don’t want more of them.

意思就是,大多数配置你没必要改,按我的来就行。emm... 这就很符合prettier 的霸道人设。

那这种行事风格会造成什么问题呢?

再举个例子,很多eslint的开源规范中,有这么一项配置: 'space-before-function-paren': ['error', 'always']

意思就是,在函数定义的名称和括号之间要加一个空格。但是霸道的prettier 默认是不加空格的,而且也没有提供开启的配置。

这就又造成了类似于前面单双引号的那种你方唱罢我登场的尴尬局面了。

此时,你有两种选择:

要么,别折腾了,听prettier 的吧,别加空格了,它狠。

或者,你跟它杠上了,偏偏要加空格。

那你的开发过程就只能这样了,当你洋洋洒洒写完一页代码,发现有点乱,格式化!然后,你的空格没了。

然后Cmd + S 保存,空格又出来了。

你要么屈服于prettier,要么就要忍受空格的反复横跳。

综述:eslint 很好,所有规则都是可配置的,但是格式化代码功能不强。

prettier 可以格式化代码,但是格式化的规则大部分只能使用默认配置,没有自主权。

所以,一旦规则冲突,最好的选择是配置eslint让它跟prettier一致,eslint-config-prettier 就是用来做这个的

配置说明

上面废话这么多,就是要让大家知其所以然,下面说一下具体的配置,让大家知其然。

配置vscode

安装我们今天的主角,eslintprettier

然后配置一下settings.json,让我们保存的时候,自动格式化一下。

{
  "eslint.autoFixOnSave": true
}

配置eslint

# 安装eslint 及 parser
yarn add -D eslint babel-eslint

# 安装流行的规范 Standard 及其相关依赖
yarn add -D eslint-config-standard eslint-plugin-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-node

# 安装 eslint react 插件
yarn add -D eslint-plugin-react

# 在 eslint-config-standard 的基础上额外加了一些规则
yarn add -D eslint-config-standard-react

# 安装hooks的插件
yarn add -D eslint-plugin-react-hooks


# 上面的是为了分开介绍,你安装的时候一次全部安装即可
yarn add -D eslint babel-eslint eslint-config-standard eslint-plugin-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-node eslint-plugin-react eslint-config-standard-react eslint-plugin-react-hooks

eslint 默认只支持ES5,所以要支持ES6或React就要做相应的配置或安装对应的插件,来帮助eslit识别这些语法。

想要识别React语法的话,需要安装eslint-plugin-react 插件。

root: true : 建议每个项目的配置文件里都加入这个配置。

可以使用eslint --init 来生成一个配置文件,然后再自己修改一下。

配置prettier

yarn add -D prettier eslint-plugin-prettier eslint-config-prettier

.eslintrc.js

// off: 0; warn: 1; error: 2
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
  root: true,
  parser: 'babel-eslint',
  parserOptions: {
    ecmaVersion: 2018,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true
    }
  },
  env: {
    es6: true,
    node: true,
    browser: true,
    commonjs: true
  },
  globals: {
    $: 'readonly'
  },
  extends: [
    'standard',
    'standard-react',
    // 如果eslint的规则于prettier的规则冲突,这个插件会让eslint的规则失效,以prettier的规则为准
    // 所以这些冲突的规则只需要在prettier中定义就行了,下面的rules里面不需要重新写一遍了
    'plugin:prettier/recommended'
  ],
  plugins: ['react-hooks'],
  rules: {
    'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks
    'react-hooks/exhaustive-deps': 'warn', // Checks effect dependencies
    'no-console': isProd ? 'error' : 'off',
    'no-debugger': isProd ? 'error' : 'off',
    'react/prop-types': 'off'
  }
}

.prettierrc.js

module.exports = {
  printWidth: 80,
  tabWidth: 2,
  useTabs: false,
  singleQuote: true,
  semi: false,
  trailingComma: 'none',
  bracketSpacing: true,
  quoteProps: 'consistent',
  jsxSingleQuote: true,
  arrowParens: 'avoid',
  endOfLine: 'lf'
}

参考

prettier

eslint

eslint-config-standard-react

说明

这篇文章是以我学习时的笔记为基础写的,如有错误,欢迎指出,感谢🙏。