前端代码规范化配置最佳实践

前言

在前端项目开发过程中,我们经常会听到代码规范化 这个词,即通过多种工具来对代码、Git记录等进行约束,使之达到某种规范。而这些规范工具多种多样,让人眼花缭乱,本文尝试通过一个工具集,来给出一种前端代码规范化的最佳实践。

本文将基于TypeScript来讲解,工具集中主要包括以下工具:

  • eslint:对代码进行风格和规范进行检查,对不符合规范的代码给出提示,同时可以进行一定程度的自动修复
  • prettier:自动格式化代码工具,根据prettier规范对代码进行修复,拥有比eslint更加强大的代码规范性修复能力
  • husky:Git hooks工具,通过配置一系列钩子,可以在git操作的不同阶段执行相应的命令
  • lint-staged:在提交代码前进行lint检查时,可以让lint只检查git暂存区(staged)的文件,而不会检查所有文件
  • commitzen:可以实现规范的提交说明的git-cz工具,提供选择的提交信息类别,快速生成提交说明,如果需要在项目中使用commitizen生成符合某个规范的提交说明,则需要使用对应的适配器
  • commit-lint:校验提交说明是否符合规范。commitzen只是一个实现规范提交说明的工具,但可能存在不使用这个工具直接用git提交的情况,那么就需要对每次提交说明进行检查是否符合规范

除了上面提到的,其他相关工具会在用到的时候再详细说明。

一、eslint & prettier

1. 首先安装eslintprettier及相关工具

shell 复制代码
npm install --save-dev eslint prettier
npm install --save-dev eslint-plugin-prettier eslint-config-prettier
npm install --save-dev @typescript-eslint/parser  @typescript-eslint/eslint-plugin
npm install --save-dev eslint-plugin-import
npm install --save-dev eslint-import-resolver-typescript

其中除了eslintprettier外的其他几个工具作用分别是:

  • eslint-plugin-prettier:将 prettier 的能力集成到 eslint 中, 按照 prettier 的规则检查代码规范性,并进行修复
  • eslint-config-prettier:让所有可能会与 prettier 规则存在冲突的 eslint rule 失效,并使用 prettier 的规则进行代码检查
  • @typescript-eslint/parser: 解析器,使 eslint 可以解析 ts 语法
  • @typescript-eslint/eslint-plugin:指定了 ts 代码规范的 plugin
  • eslint-plugin-import:对 ES6+ 的导入/导出语法进行 lint, 并防止文件路径和导入名称拼写错误的问题
  • eslint-import-resolver-typescript:这个插件为eslint-plugin-import添加了 ts 支持,详见此处

2. 配置.eslintrc.js(或者.eslingtrc.eslintrc.json

javascript 复制代码
module.exports = {
  env: {
    browser: true,
    node: true,
    es6: true,
  },
  parser: '@typescript-eslint/parser', // 解析器
  extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'], // 使用 eslint 和 typescript-eslint 建议的规则
  plugins: ['@typescript-eslint', 'prettier', 'import'], // 代码规范插件
  rules: {
    'prettier/prettier': 'error', // 不符合 prettier 规则的代码,要进行错误提示
  },
  settings: {
    'import/parsers': {
      '@typescript-eslint/parser': ['.ts', '.tsx'],
    },
    'import/resolver': {
      typescript: {
        project: 'tsconfig.json',
      },
    },
  },
};

配置.prettierrc.js(或者.prettierrc.prettierrc.json),常用规则如下:

javascript 复制代码
module.exports = {
  trailingComma: 'es5',
  singleQuote: true,
  semi: true,
  tabWidth: 2,
  printWidth: 80,
};

如果需要还可以加上相应的.eslintignore.prettierignore来忽略想要的目录/文件。

3. 向package.jsonscripts中添加命令

json 复制代码
{
  "scripts": {
    "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
    "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx ./ --fix"
  }
}

现在可以尝试一下编辑任意jsts文件并保存,通过npm run lint命令来对项目进行 lint 检查,查看是否符合规则的预期,如果安装了 ESLint VSCode 插件(强烈建议安装),还可以实时看到报错提醒。通过npm run lint:fix命令可以对不符合风格规范的代码进行自动修复。

如果需要对另外一些语法进行 lint 检查,只需添加对应的工具即可,如需要对reactreact hooks进行检查,则安装eslint-plugin-reacteslint-plugin-react-hooks即可

shell 复制代码
npm install --save-dev eslint-plugin-react eslint-plugin-react-hooks

4. 安装 VS Code 插件

强烈建议安装VS Code插件:EslintPrettier - Code formatter,通过这两个插件可以实现实时查看当前的eslint和prettier报错而不需要执行命名行检查。

顺便聊一下关于 eslint 和 prettier 的区别

  • eslint侧重影响代码质量 的问题(比如=====
  • prettier更侧重代码风格的问题(比如代码折行),以及对代码自动修复

eslint很多地方只能warning警告或者报错,但是不能自动修复,比如下面的例子:

  1. 对于=====的eslint问题

    这个是eslint报的一个问题,点击"快速修复",只能弹出几个选项,比如disable这个规则,或者展示文档,没有版本自动修复(下面的copilot不算,这个是GitHub Copilot插件AI修复,不属于自动修复)

  2. 对于prettier的代码风格问题

对于这个代码风格问题,点击"快速修复",提供了几个自动修复的选项(Fix this .../Fix all ...)

二、husky

通过上面的步骤,我们已经成功安装并配置了 eslint 相关的检查,但是我们不能仅仅依靠开发人员的自觉来保证提交到仓库的代码符合eslint规范,这时候就需要husky这样一个工具来操作git提供的一些钩子hooks,在提交代码时对代码进行 lint 检查。

1. 首先是安装husky

shell 复制代码
npm install --save-dev husky

2. 向package.jsonscripts中添加命令

json 复制代码
{
  "scripts": {
    "prepare": "husky install"
  }
}

prepare命令会在执行npm install(不带参数的情况下)之后自动执行。也就是说当我们执行npm install安装完项目依赖后会执行husky install命令,该命令会创建.husky/并指定该目录为git hooks所在的目录。这里我们先手动执行一次npm run prepare

3. 配置husky

添加pre-commit hooks:

shell 复制代码
npx husky add .husky/pre-commit // 或 npx husky set .husky/pre-commit

这将在./husky/目录下生成一个pre-commit脚本文件,在文件里添加npm run lint这个命令,添加完成后文件内容为:

shell 复制代码
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm run lint

通过上面三个步骤,我们在执行git commit或者通过git-cz工具提交时,将会先执行pre-commit脚本的内容,即执行npm run lint检查,对不符合代码规范的提交进行阻止,防止污染代码仓库。

4. 注意

上面配置husky的方式是针对 v5.0+ 的配置方式,针对 v5.0 之前的配置方式,则是在安装husky之后在package.json中添加如下配置:

json 复制代码
{
  "husky": {
    "hooks": {
      "pre-commit": "npm run lint"
    }
  }
}

这么改的原因是在husky 5.0版本中,做了破坏性的变更,导致两种配置方式不兼容,详见此处。本文推荐使用最新的配置方式。

三、lint-staged

完成husky配置之后,我们做到了通过每次git提交时都对项目做 lint 检查,防止不符合规范的代码提交到仓库,但是这带来一个问题:每次提交都将对整个项目做 lint 检查,对于一个越来越大的项目来说,这无疑是一个很耗时的操作,除此之外,对于新接入这些配置的项目,项目中可能已经存在了大量不符合规范的代码,不能要求在提交时把所有历史遗留的问题修复之后才能提交。

这个时候就需要用到lint-staged这个工具了。

1. 安装lint-staged

shell 复制代码
npm install --save-dev lint-staged

2. 在package.json中配置lint-staged

package.json中添加如下配置,配置表明在运行lint-staged的时候将只匹配srctest目录下的tstsx文件,我们可以根据自己项目的需要修改配置:

json 复制代码
{
  "lint-staged": {
    "src/**/*.{ts,tsx}": [
      "eslint"
    ],
    "test/**/*.{ts,tsx}": [
      "eslint"
    ]
  }
}

package.jsonscripts中添加命令:

json 复制代码
{
  "scripts": {
    "lint-staged": "lint-staged"
  }
}

3. 修改.husky/pre-commit脚本的内容

.husky/pre-commit脚本的内容改为npm run lint-staged

shell 复制代码
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm run lint-staged

通过上面的步骤,就完成了lint-staged的配置,这个时候再进行 git 提交时,将只检查暂存区(staged)的文件,不会检查项目所有文件,加快了每次提交 lint 检查的速度,同时也不会被历史遗留问题影响。如下图:

四、commitzen

有了上面的几个配置后,其实已经算是一个比较完善的代码规范配置了,不过还有一些其他的可以去做的事,比如 git 提交记录规范。

在多人协作开发过程中,如果不注意提交记录的规范,那么每个人可能都有自己的提交风格,如"修复了xxx的bug"、"增加了一个按钮,修改了一处文案"、"config配置文件增加了xxx字段",更有甚者会在对项目文件做了大量变更后只写一个"增加了若干功能"或"修复了若干问题"这种提交信息。

那什么才一个好的提交信息呢,我们以Angular提交信息规范来举例说明。

在 Angular 提交信息规范中,一个好的提交信息的结构应该如下所示:

plaintext 复制代码
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>

整个提交说明包括三部分:header页眉、body正文、footer页脚,在每个部分之间有一个空白行分隔,其中header部分是每次提交中必须包含的内容。

  • header:
    对于header来说,又包括三部分:
  • body:
    本地提交的详细描述,说明代码提交的详细说明
  • footer:
    主要包括本次提交的 BREAKING CHANGE(不兼容变更)和要关闭的 issue

更加详细的内容请参考Angular提交信息规范

commitzen就是这样一个工具,它可以提供可以选择的提交信息类别,快速生成符合规范的提交说明。

1. 先安装commitizencz-conventional-changelog

shell 复制代码
npm install --save-dev commitizen cz-conventional-changelog

我们在前言中提到,如果需要在项目中使用commitizen生成符合某个规范的提交说明,则需要使用对应的适配器,而cz-conventional-changelog就是符合AngularJS规范提交说明的commitzen适配器。

2. 在package.json中配置commitizen

package.json中添加如下配置,配置指明了cz工具commitizen的适配器路径:

json 复制代码
{
  "config": {
    "commitizen": {
      "path": "node_modules/cz-conventional-changelog"
    }
  }
}

package.jsonscripts中添加命令:

json 复制代码
{
  "scripts": {
    "commit": "git-cz"
  }
}

这时我们就可以使用npm run commit来代替git commit进行提交了:

3. 配置自定义提交信息规范

如果想定制项目的提交信息规范,可以使用cz-customizable适配器:

shell 复制代码
npm install --save-dev cz-customizable

然后把package.json中配置的适配器路径修改为cz-customizable的路径:

json 复制代码
{
  "config": {
    "commitizen": {
      "path": "node_modules/cz-customizable"
    }
  }
}

之后在根目录下新建一个.cz-config.js来配置自定义的规范,这里提供一个官方的示例cz-config-EXAMPLE.js,修改里面字段、内容为自己想要的规范即可

4. 生成日志记录

对于使用了commitzen的项目,还可以配套使用conventional-changelog-cli来生成开发日志:

shell 复制代码
npm install --save-dev conventional-changelog-cli

package.jsonscripts中添加命令:

json 复制代码
{
  "scripts": {
    "version": "conventional-changelog -p angular -i CHANGELOG.md -s"
  }
}

这样执行npm run version之后就可以看到生成了CHANGELOG.md日志文件了。

五、commit-lint

在配置了commitizen之后,我们可以愉快地使用npm run commit规范化提交代码,但是配置commitizen并不等于不能使用git commit或者其他工具提交,还是存在提交不规范记录说明的可能,那么就需要使用commit-lint来对每次提交信息进行限制。

1. 安装commitlint@commitlint/config-conventional

shell 复制代码
npm install --save-dev commitlint @commitlint/config-conventional

其中@commitlint/config-conventional是一个符合Angular规范的校验规则集,就像esint也需要extends一些规则集一样,commitlint也需要extends一些规则集。

2. 在package.json中配置commitlint

package.json中添加如下配置:

json 复制代码
{
  "commitlint": {
    "extends": [
      "@commitlint/config-conventional"
    ]
  }
}

package.jsonscripts中添加命令:

json 复制代码
{
  "scripts": {
    "commitlint": "commitlint --edit $1"
  }
}

注意,我们可能在别的地方见到过commitlint的下面这种写法

json 复制代码
{
  "scripts": {
    "commitlint": "commitlint -E HUSKY_GIT_PARAMS"
  }
}

同样的,这也是一种在husky v5.0 之前的写法,在新版husky中不在使用。

3. 向husky中添加commit-msg hooks

shell 复制代码
npx husky add .husky/commit-msg // 或 npx husky set .husky/commit-msg

这将在./husky/目录下生成一个commit-msg脚本文件,在文件里添加npm run commitlint这个命令,添加完成后文件内容为:

shell 复制代码
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm run commitlint

这时,如果通过git commit或其他工具在提交时没有按照规范写提交信息,那么本次提交就会被阻止,如下图:

4. 对于自定义提交信息规范的 lint 校验

上面说的@commitlint/config-conventional是针对Angular规范的校验规则集,对于使用了cz-customizable的自定义提交信息规范,就需要使用commitlint-config-cz这个工具来对自定义规范进行校验了:

shell 复制代码
npm install --save-dev commitlint-config-cz

然后把package.jsoncommitlint的配置改为:

json 复制代码
{
  "commitlint": {
    "extends": [
      "cz"
    ]
  }
}

六、总结

通过上面的这些步骤,我们算是完成了前端代码规范化的配置,到目前,我们新增的配置有:

  • .eslintrc.js
  • .eslintignore
  • .prettierrc.js
  • .prettierignore
  • .husky
    • pre-commit
    • commit-msg
    • _ husky自动生成的一个文件夹
  • package.json 下面只列出来新增的配置,对于package.json已有的字段没有列出
json 复制代码
{
  "scripts": {
    "prepare": "husky install",
    "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
    "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx ./ --fix",
    "lint-staged": "lint-staged",
    "commit": "git-cz",
    "commitlint": "commitlint --edit $1",
    "version": "conventional-changelog -p angular -i CHANGELOG.md -s"
  },
  "lint-staged": {
    "src/**/*.{ts,tsx}": [
      "eslint"
    ],
    "test/**/*.{ts,tsx}": [
      "eslint"
    ]
  },
  "commitlint": {
    "extends": [
      "@commitlint/config-conventional"
    ]
  },
  "config": {
    "commitizen": {
      "path": "node_modules/cz-conventional-changelog"
    }
  },
  "devDependencies": {
    "@commitlint/config-conventional": "^12.1.4",
    "@typescript-eslint/eslint-plugin": "^4.28.1",
    "@typescript-eslint/parser": "^4.28.1",
    "commitizen": "^4.2.4",
    "commitlint": "^12.1.4",
    "conventional-changelog-cli": "^2.1.1",
    "cz-conventional-changelog": "^3.3.0",
    "eslint": "^7.30.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-import-resolver-typescript": "^2.4.0",
    "eslint-plugin-import": "^2.23.4",
    "eslint-plugin-prettier": "^3.4.0",
    "husky": "^7.0.0",
    "lint-staged": "^11.0.0",
    "prettier": "^2.3.2"
  }
}

配置过程虽然繁琐,但是对于一个项目,特别是多人协作的大型项目来说,是必不可少的一部分。其实担心配置麻烦,导致每一个新项目都需要重新走一遍配置流程,可以考虑使用Yeoman这个脚手架工具,把一个已经完成代码规范化配置的项目作为模板,通过yo直接一键生成即可,此处是我创建的一个 demo 工程,包含了上述全部配置:github.com/JingzheWu/l...,以供参考。

参考文章和链接

相关推荐
李鸿耀5 分钟前
仅用几行 CSS,实现优雅的渐变边框效果
前端
码事漫谈25 分钟前
解决 Anki 启动器下载错误的完整指南
前端
im_AMBER1 小时前
Web 开发 27
前端·javascript·笔记·后端·学习·web
蓝胖子的多啦A梦1 小时前
低版本Chrome导致弹框无法滚动的解决方案
前端·css·html·chrome浏览器·版本不同造成问题·弹框页面无法滚动
玩代码1 小时前
vue项目安装chromedriver超时解决办法
前端·javascript·vue.js
訾博ZiBo1 小时前
React 状态管理中的循环更新陷阱与解决方案
前端
StarPrayers.2 小时前
旅行商问题(TSP)(2)(heuristics.py)(TSP 的两种贪心启发式算法实现)
前端·人工智能·python·算法·pycharm·启发式算法
一壶浊酒..2 小时前
ajax局部更新
前端·ajax·okhttp
DoraBigHead3 小时前
React 架构重生记:从递归地狱到时间切片
前端·javascript·react.js
彩旗工作室4 小时前
WordPress 本地开发环境完全指南:从零开始理解 Local by Flywhee
前端·wordpress·网站