likes
comments
collection
share

最新前端代码质量和规范工具搭配React + TS + Eslint + Stylelint + Prettier + lint-staged + Husky

作者站长头像
站长
· 阅读数 45

前言

React + TS + Eslint + Stylelint + Prettier + lint-staged + Husky项目模板,项目用了vite快速创建,换做其他脚手架也可。模板传送门

最近新起了个项目,想着把代码规范与约束做好,其实现在已经有很多脚手架、项目模板都可以直接使用,但是自己动手配下,可以完全自行搭配。

安装 eslint

安装执行yarn add --dev eslint

项目目录添加.eslintrc.js

module.exports = {
  root: true, // 指定了root为true,eslint只检查当前项目目录
  env: {
    // 提供预设的全局变量,避免eslint检查报错,例如window
    browser: true,
    node: true,
    es6: true,
  },
  extends: [
    // 继承eslint推荐的检查规则
    'eslint:recommended',
  ],
  parserOptions: {
    ecmaVersion: 'latest', // 指定ECMAScript 语法为最新
    sourceType: 'module', // 指定代码为 ECMAScript 模块
    ecmaFeatures: {
      jsx: true, // 启用jsx
    },
  },
};

项目目录添加.eslintignore,忽略一些不需要 eslint 检测的目录和文件

.eslintrc.js
node_modules
dist
.DS_Store
*.local

安装 typescript-eslint

由于项目使用的是Typescript,所以得改下 eslint 解释器,参考typescript-eslint

安装执行yarn add --dev @typescript-eslint/parser @typescript-eslint/eslint-plugin

改变.eslintrc.js

module.exports = {
  root: true, // 指定了root为true,eslint只检查当前项目目录
  env: {
    // 提供预设的全局变量,避免eslint检查报错,例如window
    browser: true,
    node: true,
    es6: true,
  },
  extends: [
    // 共享推荐的配置风格
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
  ],
  parser: '@typescript-eslint/parser',
  plugins: ['@typescript-eslint'],
  parserOptions: {
    ecmaVersion: 'latest', // 指定ECMAScript 语法为最新
    sourceType: 'module', // 指定代码为 ECMAScript 模块
    ecmaFeatures: {
      jsx: true, // 启用jsx
    },
  },
};

安装 eslint-config-airbnb 和 eslint-config-airbnb-typescript

上面我们使用了eslinttypescript推荐的代码风格。

extends: [ // 共享推荐的配置风格
  'eslint:recommended',
  'plugin:@typescript-eslint/recommended',
],

但是习惯了airbnb代码风格,而且比较流行。因此我们安装下airbnb的eslint配置(不需要可以忽略这一步)。

安装前我们需要先了解

  • eslint-config-airbnbAirbnb JavaScript风格的 eslint 共享配置库,检测规则包括ES6+React,它依赖于eslint-plugin-importeslint-plugin-reacteslint-plugin-react-hookseslint-plugin-jsx-a11y包。
  • eslint-config-airbnb-base,如果我们不需要React,可以安装这个包代替eslint-config-airbnb
  • eslint-config-airbnb-typescript,支持 typescript,依赖于eslint-config-airbnb

由于我们现在的项目是React+Ts,所以要安装eslint-config-airbnbeslint-config-airbnb-typescript这两个包。

我们先执行npm info "eslint-config-airbnb@latest" peerDependencies,了解eslint-config-airbnb的依赖包版本

npm info "eslint-config-airbnb@latest" peerDependencies

{
  eslint: '^7.32.0 || ^8.2.0',
  'eslint-plugin-import': '^2.25.3',
  'eslint-plugin-jsx-a11y': '^6.5.1',
  'eslint-plugin-react': '^7.28.0',
  'eslint-plugin-react-hooks': '^4.3.0'
}

知道依赖包版本后,我们安装对应的版本

yarn add --dev eslint-plugin-import@^2.25.3 eslint-plugin-jsx-a11y@^6.5.1 eslint-plugin-react@^7.28.0 eslint-plugin-react-hooks@^4.3.0

接着安装eslint-config-airbnbeslint-config-airbnb-typescript

yarn add --dev eslint-config-airbnb eslint-config-airbnb-typescript

按照eslint-config-airbnb-typescript 配置步骤, 现在重新调整.eslintrc.js文件

module.exports = {
  root: true,
  env: {
    browser: true,
    node: true,
    es6: true,
  },
  extends: ['airbnb', 'airbnb-typescript', 'airbnb/hooks', 'plugin:@typescript-eslint/recommended'],
  parser: '@typescript-eslint/parser', // 由于eslint默认使用espree来作为js的解释器,我们项目使用的是ts,所以换成了这个
  plugins: ['@typescript-eslint'],
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
    project: './tsconfig.json',
  },
  rule: {
    'react/react-in-jsx-scope': 'off', // React17后不需要在jsx中主动引入react
  },
};

至此,我们可以在package.json添加命令

{
  "script": {
    "lint:js": "eslint --ext .js,.jsx,.ts,.tsx ./src"
  }
}

执行yarn lint:js检测我们的代码质量

安装 prettier

执行yarn add --dev prettier

项目目录添加.prettierrc文件,我们添加常用的格式风格

{
  "singleQuote": true, // 单引号
  "trailingComma": "all", // 在多行逗号分隔的语法结构中,最后一行也添加逗号
  "printWidth": 100, // 代码宽度最大为100
  "proseWrap": "never" // 禁止markdown文本样式进行折行
}

项目目录添加.prettierignore,忽略一些不需要 prettierg 格式化的文件

**/*.png
**/*.svg
package.json
dist
.DS_Store
node_modules

至此,我们可以在package.json添加命令

{
  "script": {
    "lint:prettier": "prettier -c --write \"src/**/*\""
  }
}

执行yarn lint:prettier格式化我们项目的代码

eslint-config-prettier 和 eslint-plugin-prettier

我们先了解 eslint 和 prettier 的分工,prettier 用于代码格式化,eslint 配置代码风格、质量的校验(eslint也能负责代码格式,只是prettier更专业),两者具体区别可以参考文章

避免 eslint 和 prettier 冲突,我们需要再安装两个包eslint-config-prettiereslint-plugin-prettier

eslint-config-prettier的作用是关闭 eslint 中所有不必要的或可能与 prettier 冲突的规则,让 eslint 检测代码时不会对这些规则报错或告警。比如 eslint 规定是双引号,而我们用 prettier 格式化代码时是用单引号,会存在冲突。我们在eslint-config-prettier 代码可以看到,例如缩进、引号等格式规则都被关闭了。关闭后,我们可以完全自定义 prettier 来格式化我们的代码,而不受 eslint 影响。

eslint-plugin-prettier 是一个 ESLint 插件。上面我们说关闭了一些 eslint 的代码格式规则。假设我们约定 prettier 规则使用双引号,然而敲代码写成单引号,我还是希望能够按 prettier 的规则给我一些代码不规范的报错或警告提示。那么eslint-config-prettier是关闭了 eslint 中与 prettier 冲突的规则,eslint-plugin-prettier就是开启了以 prettier 为准的规则,并将报告错误给 eslint。

说完了上面的解释,我们开始安装执行 yarn add --dev eslint-config-prettier eslint-plugin-prettier

安装后我们只需要在.eslintrc.js文件添加一行即可

{
  extends: [
    // ...
    'plugin:prettier/recommended'
  ]
}

plugin:prettier/recommende的作用会帮我们扩展成下面的代码

{
  extends: ['prettier'],
  plugins: ['prettier'],
  rules: {
    'prettier/prettier': 'error',
    'arrow-body-style': 'off',
    'prefer-arrow-callback': 'off',
  },
}

我们也可以自行改变下一些规则,比如

{
  rules: {
    'prettier/prettier': [
      'error',
      {
        singleAttributePerLine: false, // 不强制要求一个属性占一行
      }
    ]
  }
}

至此,我们项目eslintprettier的配置就完成了,我们再来看看完整的.eslintrc.js文件

module.exports = {
  root: true, // 指定了root为true,eslint只检查当前项目目录
  env: {
    // 提供预设的全局变量,避免eslint检查报错,例如window
    browser: true,
    node: true,
    es6: true,
  },
  extends: [
    // 共享推荐的配置风格
    'airbnb',
    'airbnb-typescript',
    'airbnb/hooks',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
  ],
  parser: '@typescript-eslint/parser', // 由于eslint默认使用espree来作为js的解释器,我们项目使用的是ts,所以换成了这个
  plugins: ['@typescript-eslint'],
  parserOptions: {
    ecmaVersion: 'latest', // 指定ECMAScript 语法为最新
    sourceType: 'module', // 指定代码为 ECMAScript 模块
    ecmaFeatures: {
      jsx: true, // 启用jsx
    },
    project: './tsconfig.json',
  },
  rules: {
    'react/react-in-jsx-scope': 'off', // React17后不需要在jsx中主动引入react
    'prettier/prettier': [
      'error',
      {
        singleAttributePerLine: false, // 不强制要求一个属性占一行
      }
    ]
  },
};

安装 stylelint

检测 css 样式代码质量,其实很多项目都是不检测的,如果不做这步可以忽略。

按照官网 docs,我们开始安装

yarn add --dev stylelint stylelint-config-standard

项目目录中添加.stylelintrc.js文件

module.exports = {
  extends: ['stylelint-config-standard'],
};

我们使用了官方推荐的stylelint-config-standard配置就好

至此,我们可以在package.json添加命令

{
  "script": {
    "lint:style": "stylelint \"**/*.css\""
  }
}

执行yarn lint:style检测我们的 css 代码质量

同样的,我们统一用 prettier 来格式化 css 代码。 需要安装stylelint插件来避免与prettier冲突。

  • stylelint-config-prettier,和eslint-config-prettier类似,作用是关闭 stylelint 所有不必要的或可能与 prettier 冲突的规则。但是在 Stylelint v15 版本之后,Stylelint 默认关闭了所有与 prettier 相冲突的风格规则,所以不需要安装stylelint-config-prettier了。
  • stylelint-prettier,和eslint-plugin-prettier类似,开启了以 prettier 为准的规则,并将报告错误给 stylelint。

上面了解后,我们只需要安装stylelint-prettier

安装 stylelint-prettier

执行安装yarn add --dev stylelint-prettier

修改.stylelintrc.js文件

module.exports = {
  extends: ['stylelint-config-standard', 'stylelint-prettier/recommended'],
};

搞定。

代码质量检测小结回顾

至此我们的package.json文件添加了三条命令

{
  "scripts": {
    "lint:js": "eslint --ext .js,.jsx,.ts,.tsx ./src",
    "lint:style": "stylelint \"**/*.css\"",
    "lint:prettier": "prettier -c --write \"src/**/*\""
  }
}
  • lint:js,检查 js 和 ts 代码质量
  • lint:style,检查 css 代码质量
  • lint:prettier,格式化所有代码,包括 js、ts、css、json、md 等。

注意lint:prettier只管修复代码格式问题。

如果我们要自动修复代码质量问题,例如js代码中你使用了var声明变量,需要自动修复成letconst。那么我们可以再添加多两条命令。

{
  "scripts": {
    "lint:js:fix": "eslint --ext .js,.jsx,.ts,.tsx ./src --fix",
    "lint:style:fix": "stylelint \"**/*.css\" --fix"
  }
}

那么执行了上面的命令,就是把代码所有质量和格式的问题都会尽可能帮你修复好。按个人喜好来讲,我不推荐这样做,就是只使用lint:prettier就好,对于代码质量问题,应该自身平时要养成良好的代码习惯,尽量减少这类问题。如果有代码质量问题,自己根据错误报告去逐一手动修复即可。

安装 lint-staged

由于检查代码命令是对整个项目代码有效,有时候我们只想对自己改动的代码进行检查,而忽略项目其他代码。我们可以使用lint-staged,它可以让我们执行检查命令只对 git 缓存区的文件有效。

安装执行yarn add --dev lint-staged

然后再package.json添加代码

{
  "scripts": {
    "lint-staged": "lint-staged"
  },
  "lint-staged": {
    "**/*.css": "stylelint \"**/*.css\"",
    "**/*.{js,jsx,ts,tsx}": "eslint --ext .js,.jsx,.ts,.tsx",
    "**/*.{js,jsx,tsx,ts,css,md,json}": "prettier --ignore-unknown --write"
  }
}

上面的文件匹配规则

{
  "lint-staged": {
    "**/*.css": "stylelint", // 匹配css文件用stylelint检查
    "**/*.{js,jsx,ts,tsx}": "eslint --ext .js,.jsx,.ts,.tsx", // 匹配js,jsx,ts,tsx文件用eslint检查
    "**/*.{js,jsx,tsx,ts,css,md,json}": "prettier --ignore-unknown --write" // 匹配js,jsx,tsx,ts,css,md,json文件统一用prettier格式化代码
  },
}

这 3 个匹配规则的执行是存在竞争关系,但是无所谓,只要 stylelint 或 eslint 谁先检查出错误报告,都会终止匹配执行。我们必须得一一改正才能养成良好习惯,减少类似问题出现。

我们改动代码并git add .后,可以执行yarn lint-staged。一旦 prettier 格式化代码成功,并且 stylelint 和 eslint 无错误输出,那么 lint-staged 即执行成功,代表我们的代码通过检测。

安装 husky

由于前面都是需要手动操作的,husky 可以让我们在 git 提交的时候自动执行命令。

我们安装执行yarn add --dev husky,安装官网步骤

我们在package.json添加命令

{
  "scripts": {
    "prepare": "husky install"
  }
}

然后执行这条命令yarn prepare,husky 执行初始化,可以发现我们的项目目录多了.husky文件夹,代表初始化成功。

接着我们执行

npx husky add .husky/pre-commit "npm run lint-staged"

大功告成。之后我们 git 提交的时候会自动执行npm run lint-staged命令,即检查 git 缓存区的代码问题,若存在问题,lint-staged会终止并报错,git 提交自然不会成功。

注意

如果使用mac的Sourcetree软件(Git图形工具)提交代码,可能会提交失败。可参考husky官网的做法。 在自己电脑上添加文件~/.huskyrc,内容如下

# ~/.huskyrc
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

完整的代码项目

到这里,我们的项目就算配置完成了,我们来看下完整的package.json

{
  "name": "vite-react-ts-eslint-prettier-husky",
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "lint:js": "eslint --ext .js,.jsx,.ts,.tsx ./src",
    "lint:style": "stylelint \"**/*.css\"",
    "lint:prettier": "prettier -c --write \"src/**/*\"",
    "lint-staged": "lint-staged",
    "prepare": "husky install"
  },
  "lint-staged": {
    "**/*.css": "stylelint",
    "**/*.{js,jsx,ts,tsx}": "eslint --ext .js,.jsx,.ts,.tsx",
    "**/*.{js,jsx,tsx,ts,css,md,json}": "prettier --ignore-unknown --write"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@types/react": "^18.0.27",
    "@types/react-dom": "^18.0.10",
    "@typescript-eslint/eslint-plugin": "^5.54.1",
    "@typescript-eslint/parser": "^5.54.1",
    "@vitejs/plugin-react": "^3.1.0",
    "eslint": "^8.35.0",
    "eslint-config-airbnb": "^19.0.4",
    "eslint-config-airbnb-typescript": "^17.0.0",
    "eslint-config-prettier": "^8.7.0",
    "eslint-plugin-import": "^2.25.3",
    "eslint-plugin-jsx-a11y": "^6.5.1",
    "eslint-plugin-prettier": "^4.2.1",
    "eslint-plugin-react": "^7.28.0",
    "eslint-plugin-react-hooks": "^4.3.0",
    "husky": "^8.0.3",
    "lint-staged": "^13.2.0",
    "prettier": "^2.8.4",
    "stylelint": "^15.2.0",
    "stylelint-config-standard": "^30.0.1",
    "stylelint-prettier": "^3.0.0",
    "typescript": "^4.9.3",
    "vite": "^4.1.0"
  }
}

最终项目仓库➡️github.com/Zeng-J/reac…

Vscode插件

在最后,我们如果使用vscode开发,一定要安装ESlint、Stylelint、Prettier这三个插件,只要项目安装了ESlint和Stylelint包,那么Vscode可以实时把代码质量问题报红提示,对于强迫症的人,肯定想及时把报红消灭,当我们养成良好习惯,类似问题自然就很少发生。(有时候解决了问题,报红还是在,或许关闭项目,重新打开vscode就好了😆)

Prettier插件可以让我们随时格式化代码,每当敲完一段代码后,自己都会习惯性shift + alt + f代码格式化,当然你也可以vscode配置自动保存、自动格式化。