Skip to content

把时间花在更有意义的问题上:记录eslint开箱即用的规范和vscode配置 #23

@qunzi0214

Description

@qunzi0214

关于规范

是否在犹豫到底句尾加不加分号?
是否有过和同事争执哪种写法更优雅更易维护的经历?
是否争执过后痛不欲生的发现人和人之间无法互相理解?

参考下 standard 的哲学吧!

Just use standard and move on. There are actual real problems that you could spend your time solving! :P

确定一个开箱即用的规范然后就严格执行吧!(如果你有拍板能力的话...

Eslint基本配置和vscode插件配置

尽管在代码格式化上面有许多好用的命令行工具: prettierstandardtslint ...
但是考虑到不同技术栈对格式化要求不同、想要同时使用某几种风格、灵活性等情况,个人还是更加倾向基于 eslint 通过扩展和插件来配置项目代码规范的方式。目前各类热门的格式化工具或风格也都有 eslint 的扩展或者插件。

同时,基于 eslint 来扩展这种方式,无需为不同业务场景或项目安装额外的IDE插件或命令行工具

Eslint 基本配置

关于各种类型的 Eslint 配置文件如果同时出现,优先级如下:(通常不会这么做)

  1. .eslintrc.js
  2. .eslintrc.yaml
  3. .eslintrc.yml
  4. .eslintrc.json
  5. .eslintrc
  6. package.json

.eslintrc.json 为例,常见的核心配置项如下:

.eslintrc.json

{
  // 解析器 
  "parser": "esprima",
  // 定义一组预定义的全局变量
  "env": { "es6": true },
  // 解析器选项(不同的解析器选项可能会不同)
  "parserOptions": {
    // ECMAScript版本(只启用语法,不启用新全局变量,如Set)
    "ecmaVersion": 5,
    // 额外的语言特性
    "ecmaFeatures": {},
    // ECMAScript模块
    "sourceType": "module"
  },
  // 可共享的配置包
  "extends": [],
  // 插件提供额外的校验规则
  "plugins": [],
  // 具体的规则
  "rules": {
    // ...
  }
}

关于 extendsplugins
传入 plugins 选项的插件包会提供额外的规则实现,原理是在 eslint 将代码解析为AST后将上下文传入规则对应的回调函数,回调函数会进行一系列的校验操作。
传入 extends 选项的扩展包本身并不提供额外的规则实现,仅仅是提供一个预设的 .eslintrc.json 与本地的 .eslintrc.json 进行增量合并(本地的配置项优先级高于扩展包) 。如果传入多个扩展包的数组,相同的配置项后者会覆盖前者。

扩展包 eslint-config-standard 源码

{
  "parserOptions": {
    "ecmaVersion": 2021,
    "ecmaFeatures": {
      "jsx": true
    },
    "sourceType": "module"
  },

  "env": {
    "es2021": true,
    "node": true
  },

  "plugins": [
    "import",
    "node",
    "promise"
  ],

  "globals": {
    "document": "readonly",
    "navigator": "readonly",
    "window": "readonly"
  },

  "rules": {
    "no-var": "warn",

    // ...
  }
}

因此本地安装依赖后,只需要在配置文件中声明扩展,无需任何额外配置项。需要注意的是,扩展包一般会将依赖声明为 peerDependenciesnpm 不同版本对于 peerDependencies 处理方式不太一样。

本地 .eslintrc.json

{
  "extends": ["standard"] // eslint-config- 可省略
}

Vscode的插件配置

  1. 首先需要安装插件 ESLint
  2. 打开 setting.json ,添加如下配置
{
    "vetur.format.enable": false, // 关闭其他插件的format
    "editor.tabSize": 2,
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true // 保存的时候fix可以格式化的eslint问题
    },
    "editor.formatOnSave": true, // 开启保存格式化
    "eslint.format.enable": true, // 将eslint作为formatter
    "eslint.validate": [ // 哪些语言需要被eslint校验
        "javascript",
        "javascriptreact"
    ],
}

记录一下目前用到的一些风格方案

1. React + React Hooks + Standard

standard + standard-jsx

npm install --save-dev eslint-config-standard eslint-config-standard-jsx eslint-plugin-promise eslint-plugin-import eslint-plugin-node eslint-plugin-react

react-hooks

npm install --save-dev eslint-plugin-react-hooks

jsx-a11y

npm install --save-dev eslint-plugin-jsx-a11y

.eslintrc.json

{
  "extends": [
    "standard",
    "standard-jsx"
  ],
  "plugins": [
    "react-hooks",
    "jsx-a11y"
  ],
  "rules": {
    "no-console": "warn",
    "comma-dangle": [
      "error",
      "always-multiline"
    ]
  }
}

2. React + React Hooks + TS + Standard

standard-with-typescript

npm install --save-dev eslint@7 eslint-plugin-promise@4 eslint-plugin-import@2 eslint-plugin-node@11 @typescript-eslint/eslint-plugin@4 eslint-config-standard-with-typescript

react + react-hooks + jsx-a11y

npm install --save-dev eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y

tsconfig.json

{
  "compilerOptions": {
    "target": "es6",
    "strict": true,
    "module": "esnext",
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "jsx": "react",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "lib": [
      "es2015",
      "es2016",
      "es2017",
      "dom"
    ],
    "resolveJsonModule": true
  },
  "includes": [
    "./declare/externals.d.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}

.eslintrc.json

{
  "extends": [
    "standard-with-typescript"
  ],
  "parserOptions": {
    "project": "./tsconfig.json"
  },
  "plugins": [
    "react",
    "react-hooks",
    "jsx-a11y"
  ],
  "rules": {
    "no-console": "warn",
    "comma-dangle": [
      "error",
      "always-multiline"
    ]
  }
}

3. Vue + Airbnb

babel-eslint + eslint-plugin-vue

npm install --save-dev eslint-plugin-vue babel-eslint

airbnb-base

npx install-peerdeps --dev eslint-config-airbnb-base

.eslintrc.js

module.exports = {
  root: true,
  env: {
    node: true,
  },
  extends: ['plugin:vue/recommended', 'airbnb-base'],
  parserOptions: {
    parser: 'babel-eslint',
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'import/no-unresolved': 'off',
    'vue/max-attributes-per-line': ['error', {
      singleline: 3,
      multiline: {
        max: 1,
        allowFirstLine: false,
      },
    }],
  },
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    javascriptjavascript 相关知识点personal article零碎的个人知识点记录

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions