前端工程化之代码提交规范Eslint + Prettier + Husky + Commitlint+ lint-staged

956 阅读9分钟

前言

团队开发的成员越来越多,项目都是由多个人进行开发和维护,每个人的代码书写习惯和风格又不尽相同,commit 的提交log 也是乱七八糟,为以后的开发和维护增添了很多困难,所以规范和约束在多人协作下,就显得尤为重要。

本文将以React 项目为例,在项目中配置 eslint + pretttier + husky + commitLint 代码提交规范

1、创建项目

进入你想创建项目的目录,运行 yarn create vite 然后根据提示输入项目名,然后依次选择 react、react-ts 即可创建一个 React+TS 项目。

创建后按照提示进入项目文件夹并安装依赖,然后运行 yarn dev 即可启动项目。不同于 Vite2,可以看到 Vite3 的默认端口号是 5173。

打开 http://localhost:5173/ 可以看到默认页面。

2、配置Eslint

2.1 安装依赖包

npm install eslint -D

2.2 安装成后 生成配置文件

// 按指示一路回车即可 
npx eslint --init

2.3 配置.eslintrc.js, 直接用下方的eslintrc替换自动生成的即可,可避免很多坑

这里会出现一个 'module' is not defined报错所以在配置中加入 node: true

module.exports = {
    'env': {
        'browser': true,
        'es2021': true,
        'node': true // 解决 'module' is not defined报错。
    },
    'extends': [
        'eslint:recommended',
        'plugin:react/recommended',
        'plugin:react-hooks/recommended',
        'plugin:@typescript-eslint/recommended',
        'prettier'
    ],
    'overrides': [],
    'parser': '@typescript-eslint/parser',
    'parserOptions': {
        'ecmaVersion': 'latest',
        'sourceType': 'module'
    },
    'plugins': [
        'react',
        '@typescript-eslint',
        'simple-import-sort'
    ],
    'rules': {
        'no-console': 'off',
        'no-param-reassign': 'off',
        'no-empty-function': 'off',
        'no-async-promise-executor': 'off',
        'quotes': ['error', 'single'],
        'prefer-destructuring': 'off',
        'react/react-in-jsx-scope': 'off',
        'react/prop-types': 'off',
        '@typescript-eslint/no-shadow': 'off',
        '@typescript-eslint/no-unused-vars': 'off',
        '@typescript-eslint/ban-ts-comment': 'off',
        '@typescript-eslint/no-non-null-assertion': 'off',
        // 'array-bracket-spacing': ['error', 'always'], // 数组前后留空格
        'object-curly-spacing': ['error', 'always'], // 对象前后留空格
        'semi': ['error', 'never'], // ;分号省略
        'comma-dangle': ['error', 'never'], // ,逗号省略
        'simple-import-sort/imports': 'error',
        'simple-import-sort/exports': 'error',
        '@typescript-eslint/no-unused-expressions': 'off',
        '@typescript-eslint/ban-types': 'off',
        '@typescript-eslint/no-explicit-any': 'off',
        '@typescript-eslint/no-empty-function': 'off'
    }
}

2.4 使用eslint命令,在package的script中添加,fix表示可自动修复简单的问题。

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

OK,到这里,我们可以先来测试一下,写一行未使用的代码,执行 npm run lint,然后就可以看到如下报错,提示userName 未引用

2.5 设置忽略文件 .eslintignore

dist/*
node_modules/*
*.json
public

3、配置 prettier 格式化代码

一般 ESLint 用于检测代码风格代码规范,Prettier 用于对代码进行格式化。

3.1 先安装依赖

npm install prettier -D

3.2 安装 Prettier - Code formatter 插件

3.3 配置.prettierrc.js文件

重启 vscode 后,我们在 .prettierrc.js 文件中配置的代码风格才会生效

module.exports = {
  printWidth: 100, // 一行的字符数,如果超过会进行换行,默认为80
  tabWidth: 2, // 一个 tab 代表几个空格数,默认为 2 个
  useTabs: false, // 是否使用 tab 进行缩进,默认为false,表示用空格进行缩减
  singleQuote: true, // 字符串使用单引号
  semi: false, // 行尾不使用分号
  trailingComma: "none", // 是否使用尾逗号
  htmlWhitespaceSensitivity: "strict", // HTML空白敏感度
  bracketSpacing: true, // 对象大括号直接是否有空格,默认为 true,效果:{ a: 1 }
  proseWrap: "never" // 换行设置
}

在 packages.json 中的 script 配置命令

"scripts": {
    "format": "prettier --write \"src/**/*.+(js|ts|jsx|tsx)\"",
}

运行该命令,会将我们项目中的文件都格式化一遍,后续如果添加其他格式的文件,可在该命令中添加,例如:.less后缀的文件

3.4、设置 .prettierignore 忽略文件

node_modules/**
dist/**
public/**
doc/**

3.5、解决ESLint与Prettier的冲突

ESLint

  • 目的:ESLint 主要用于发现代码中的问题,如潜在的错误、不一致的编码风格、未使用的变量等。
  • 可配置性:ESLint 允许自定义规则,使其可以强制实施特定的编码标准和最佳实践。

Prettier

  • 目的:Prettier 主要用于自动格式化代码,以保持代码风格的一致性。
  • 风格规则:Prettier 有一套默认的风格规则,例如缩进、行宽、引号等,并且这些规则不太可配置。

冲突原因

  • 冲突通常发生在两个工具对某些代码风格规则有不同的处理方式。例如,ESLint 可能要求使用单引号,而 Prettier 默认使用双引号。
  • 当这两个工具同时运行时,它们可能会对代码的同一部分提出不同的修改建议,从而造成冲突。

安装依赖包

npm install eslint-config-prettier eslint-plugin-prettier -D

eslint-config-prettier 基于 prettier 代码风格的 eslint 规则,即eslint使用pretter规则来格式化代码。

eslint-plugin-prettier 禁用所有与格式相关的 eslint 规则,解决 prettier 与 eslint 规则冲突,确保将其放在 extends 队列最后,这样它将覆盖其他配置

3.6 增加 .vscode 配置 settings.json 自动完成格式化

// settings.json
{
  // 保存的时候自动格式化
  "editor.formatOnSave": true,
  // 默认格式化工具选择prettier
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

配置完成之后,我们保存代码的时候就可以自动完格式化了

4、配置 husky

4.1、安装并初始化husky

// 初始化husky。 
// 1将prepare脚本添加到package 
// 2、根目录创建.husky文件夹,包含pre-commit钩子
npm install husky -D

npx husky-init

4.2 安装并配置lint-staged

只检查通过git add添加到暂存区的文件,避免每次检查都把整个项目的代码都检查一遍,从而提高效率

npm install lint-staged -D

4.3 配置packages.json 命令

// 设置lint-staged;提交时prettier代码格式化,eslint检查修复
{ 
  "lint-staged": {
    "*.{js,ts,jsx,tsx}": [
      "prettier --write",
      "eslint --fix"
    ],
    "*.{js,json,ts,tsx,css,scss,html}": [
      "prettier --write"
    ]
  },
}

4.4 修改.husky/pre-commit文件,使提交时能执行lint-staged钩子

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npm run lint-staged

5、配置 commit-msg

commitlint 检查提交消息是否符合常规提交格式,用于在每次提交时生成符合规范的commit消息。

5.1 安装commit-msg

npm install @commitlint/config-conventional @commitlint/cli --save-dev

5.2 添加 commitlint.config.js 配置文件

module.exports = {
  extends: ["@commitlint/config-conventional"],
  rules: {
    // type 类型定义
    "type-enum": [
      2,
      "always",
      [
        "feat", // 新功能 feature
        "fix", // 修复 bug
        "docs", // 文档注释
        "style", // 代码格式(不影响代码运行的变动)
        "refactor", // 重构(既不增加新功能,也不是修复bug)
        "perf", // 性能优化
        "test", // 增加测试
        "chore", // 构建过程或辅助工具的变动
        "revert", // 回退
        "build", // 打包
      ],
    ],
    // subject 大小写不做校验
    // 自动部署的BUILD ROBOT的commit信息大写,以作区别
    "subject-case": [0],
  },
};

@commitlint/config-conventional 这是一个规范配置,标识采用什么规范来执行消息校验, 这个默认是

Angular

的提交规范

5.3 执行以下命令添加commitlint钩子

npx husky add .husky/commit-msg "npm run commitlint"

5.4 在packages.json 配置

"scripts": {
    "commitlint": "commitlint --config commitlint.config.js -e -V"
},

按上面步骤修改完,我们在提交代码时候,如果随便写一个提交message将会报错,不允许提交,如下所示:

5.5 正常提交

git commit -m 'feat: 测试一下'

6、自定义代码提交规则

自定义提交规则可以根据团队开发规范来进行额外配置,目前我所在的团队提交规则是,会把每个需求的产品文档链接关联到每一个feature,这样后续要是有问题,也方便找到对应的产品文档.

配置如下

主要就增加了plugin 和 三个rule 规则

'must-add-document-url": [2, "always"]', // 加入自定义规则
'body-max-line-length': [2, 'always', 200], // body最大内容行数
'header-max-length': [2, 'always', 200], // header 最大长度

module.exports = {
  extends: ["@commitlint/config-conventional"],
  rules: {
    // type 类型定义
    "type-enum": [
      2,
      "always",
      [
        "feat", // 新功能、新特性feature
        "fix", // 修复 bug
        "docs", // 文档修改
        "style", // 代码格式(不影响代码运行的变动)
        "refactor", // 代码重构
        "perf", // 优化相关,比如提升性能、体验
        "test", // 测试用例修改
        "chore", // 其他修改, 比如改变构建流程、或者增加依赖库、工具等
        "revert", // 回滚上一个版本
        "build", // 编译相关的修改,例如发布版本、对项目构建或者依赖的改动
      ],
    ],
    // subject 大小写不做校验
    // 自动部署的BUILD ROBOT的commit信息大写,以作区别
    "subject-case": [0],
    "must-add-document-url": [2, "always"], // 加入自定义规则
    'body-max-line-length': [2, 'always', 200], // 加入自定义规则
    'header-max-length': [2, 'always', 200], // 加入自定义规则
  },
  plugins: [
    {
      rules: {
        "must-add-document-url": ({ type, body }) => {
          const ALIYUN_DOCUMENT_PREFIX = "https://devops.aliyun.com";

          // 排除的类型
          const excludeTypes = ["chore", "refactor", "style", "test"];
          if (excludeTypes.includes(type)) {
            return [true];
          }

          return [
            body && body.includes(ALIYUN_DOCUMENT_PREFIX),
            `提交的内容中必须包含云效相关文档地址`,
          ];
        },
      },
    },
  ],
};

如果不需要特殊规则

配置成以下即可。

module.exports = {
  extends: ['@commitlint/config-conventional']
}

然后再来测试一下

git commit -m "feat: 测试自定义提交规则"

正确提交

'feat: 测试自定义提交规则'

正常提交上来了

7、总结

本文从实战出发,为一个React 项目添加了eslint + prettier + husky + lint-staged项目规范以保证项目的质量、统一格式、风格。希望大家能从中学到知识。代码已经上传到github上, 点击这里即可查看。

参考文章

# 代码提交规范-ESLint+Prettier+husky+Commitlint

commitlint 从0到1 (git commit 校验工具)