eslint+typescript+prettier+husky+lint-staged规范前端代码配置

2,297 阅读4分钟

痛点

  • 代码可读性低代码
  • 代码规范落地难
  • 代码格式难统一
  • 代码质量低下

为什么用 eslint不直接用 tslint?

In the TypeScript 2019 Roadmap, the TypeScript core team explains that ESLint has a more performant architecture than TSLint and that they will only be focusing on ESLint when providing editor linting integration for TypeScript. For that reason, I would recommend using ESLint for linting TypeScript projects.


1. 安装 eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin:

yarn add eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --dev
or
npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
  • eslint: The core ESLint linting library
  • @typescript-eslint/parser: ESLint对TypeScript代码进行解析
  • @typescript-eslint/eslint-plugin: 包含一组特定的TypeScript的ESLint规则的插件

2. 在项目根目录新建一个配置文件.eslintrc.js。最好不要用.eslintrc.json(.eslintrc.js可以写注释)

.eslintrc.js文件配置
module.exports =  {
  parser:  '@typescript-eslint/parser',  // Specifies the ESLint parser
  extends:  [
    'plugin:@typescript-eslint/recommended',  // Uses the recommended rules from the @typescript-eslint/eslint-plugin
  ],
 parserOptions:  {
    ecmaVersion:  2018,  // Allows for the parsing of modern ECMAScript features
    sourceType:  'module',  // Allows for the use of imports
  },
  rules:  {
    // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
    // e.g. "@typescript-eslint/explicit-function-return-type": "off",
  },
};
如果使用TypeScript + React开发 ,则应该安装eslint-plugin-react 依赖项,可以使用以下配置:
yarn add eslint-plugin-react --dev
or
npm install eslint-plugin-react --save-dev
如果使用react hooks api,则应该安装eslint-plugin-react-hooks 依赖项
yarn add eslint-plugin-react-hooks --dev
or
npm install eslint-plugin-react-hooks --save-dev
module.exports =  {
  parser:  '@typescript-eslint/parser',  // Specifies the ESLint parser
  extends:  [
    'plugin:react/recommended',  // Uses the recommended rules from @eslint-plugin-react
    'plugin:@typescript-eslint/recommended',  // Uses the recommended rules from @typescript-eslint/eslint-plugin
  ],
  parserOptions:  {
  ecmaVersion:  2018,  // Allows for the parsing of modern ECMAScript features
  sourceType:  'module',  // Allows for the use of imports
  ecmaFeatures:  {
    jsx:  true,  // Allows for the parsing of JSX
  },
  },
  rules:  {
    // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
    // e.g. "@typescript-eslint/explicit-function-return-type": "off",
  },
  settings:  {
    react:  {
      version:  'detect',  // Tells eslint-plugin-react to automatically detect the version of React to use
    },
  },
};
如果使用TypeScript + Vue开发 ,则应该安装eslint-plugin-vue 依赖项,可以使用以下配置:
module.exports =  {
  parser:  '@typescript-eslint/parser',  // Specifies the ESLint parser
  extends:  [
    'plugin:react/recommended',  // Uses the recommended rules from @eslint-plugin-react
    'plugin:@typescript-eslint/recommended',  // Uses the recommended rules from @typescript-eslint/eslint-plugin
    'plugin:vue/essential'
  ],
  parserOptions:  {
  ecmaVersion:  2018,  // Allows for the parsing of modern ECMAScript features
  sourceType:  'module',  // Allows for the use of imports
  ecmaFeatures:  {
    jsx:  true,  // Allows for the parsing of JSX
  },
  },
  rules:  {
    // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
    // e.g. "@typescript-eslint/explicit-function-return-type": "off",
  },
  settings:  {
    react:  {
      version:  'detect',  // Tells eslint-plugin-react to automatically detect the version of React to use
    },
  },
};

3. Adding Prettier

yarn add prettier eslint-config-prettier eslint-plugin-prettier --dev
or
npm install prettier eslint-config-prettier eslint-plugin-prettier --save-dev
  • ==prettier:== The core prettier library
  • ==eslint-config-prettier:== Disables ESLint rules that might conflict with prettier
  • ==eslint-plugin-prettier:== Runs prettier as an ESLint rule

==在项目根目录新建一个配置文件.prettierrc.js。文件配置也可以放到.eslintrc.js中==

module.exports =  {
  semi:  true,
  trailingComma:  'all',
  singleQuote:  true,
  printWidth:  120,
  tabWidth:  2,
};

Next, the .eslintrc.js file needs to be updated:

module.exports =  {
  parser:  '@typescript-eslint/parser',  // Specifies the ESLint parser
  extends:  [
    'plugin:@typescript-eslint/recommended',  // Uses the recommended rules from the @typescript-eslint/eslint-plugin
    'prettier/@typescript-eslint',  // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
    'plugin:prettier/recommended',  // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
  ],
  parserOptions:  {
    ecmaVersion:  2018,  // Allows for the parsing of modern ECMAScript features
    sourceType:  'module',  // Allows for the use of imports
  },
  rules: {
    // 自定义 prettier 规则
    'prettier/prettier': [
      'error',
      {
        semi: true,
        trailingComma: 'all',
        singleQuote: true,
        printWidth: 120,
        tabWidth: 2
      }
    ]
  }
};

The advantage of having prettier setup as an ESLint rule using eslint-plugin-prettier is that code can automatically be fixed using ESLint's --fix option.


4.Automatically Fixing Code (VS Code)

For a good developer experience, it's useful to setup your editor to automatically run ESLint's automatic fix command (i.e. eslint --fix) whenever a file is saved. Since i'm using VS Code, here is the config required in the settings.json file in VS Code to get automatic fixing whenever saving a file:

"eslint.autoFixOnSave": true,
"eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact"
],

If you've also set the editor.formatOnSave option to true in your settings.json, you'll need to add the following config to prevent running 2 formatting commands on save for JavaScript and TypeScript files:

"editor.formatOnSave":  true,
"[javascript]":  {
  "editor.formatOnSave":  false,
},
"[javascriptreact]":  {
  "editor.formatOnSave":  false,
},
"[typescript]":  {
  "editor.formatOnSave":  false,
},
"[typescriptreact]":  {
  "editor.formatOnSave":  false,
},

5. 安装husky lint-staged

yarn add husky lint-staged --dev
or
npm install husky lint-staged --save-dev

package.json文件

"scripts": {
    "eslint": "eslint src --ext .ts",
    "lint": "tsc src/**/*.ts",
    "precommit": "lint-staged"
  },
  "lint-staged": {
    "src/**/*.{ts,tsx,jsx,vue}": [
      "prettier --write", // 最好不加
      "eslint --fix", //
      "git add"
    ]
  },

6.简单的.eslintrc.js文件配置

module.exports = {
  parser: '@typescript-eslint/parser', // Specifies the ESLint parser
  extends: [
    'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin
    'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
    'plugin:prettier/recommended', // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
  ],
  parserOptions: {
    ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
    sourceType: 'module', // Allows for the use of imports
  },
  plugins: ['@typescript-eslint', 'react-hooks', 'prettier'],
  globals: {
    // 这里填入你的项目需要的全局变量
  },
  rules: {
    // 这里填入你的项目需要的个性化配置
    // 自定义 prettier 规则
    'prettier/prettier': [
      'error',
      {
        semi: true,
        trailingComma: 'all',
        singleQuote: true,
        printWidth: 120,
        tabWidth: 2,
      },
    ],
    // 一个缩进必须用两个空格替代
    indent: [
      'error',
      2,
      {
        SwitchCase: 1,
        flatTernaryExpressions: true,
      },
    ],
    'react-hooks/rules-of-hooks': 'error', // react hooks校验
    'react-hooks/exhaustive-deps': 'warn',
    // 禁止使用console
    'no-console': 'error',
    'no-return-assign': 'warn',
    'array-callback-return': 'error',
    'guard-for-in': 'off',
    'max-len': ['error', { code: 120 }], // 字符串最大长度
    // 类和接口的命名必须遵守帕斯卡命名法,比如 PersianCat
    '@typescript-eslint/class-name-casing': 'error',
    '@typescript-eslint/explicit-member-accessibility': 'off',
    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/no-explicit-any': 'off',
    '@typescript-eslint/camelcase': 'off',
    '@typescript-eslint/no-var-requires': 'off',
  },
};