背景
团队协作中经常遇到这样的问题:
- 代码风格不统一
可以使用 linter 使代码风格统一。
- 使用 linter 检测之后有非常多的格式问题,手动修改很麻烦
可以使用 linter 命令来修复错误。比如 eslint 就可以 eslint --fix。
- 使用命令修复的时候,不小心修改了他人代码,很容易造成冲突。
- 如果一个项目以前没有用过 linter,如何最方便地开始使用并且尽量不改动之前的代码?
解决以上问题的一个方案就是,在提交代码的时候,自动修复格式问题,并且只修复自己改动的代码。
具体实现可以借助于 husky + lint-staged + prettier 这几个工具。
最终效果如下图所示:

使用
首先安装包 eslint 相关的包,如:
# Node.js 可以使用 eslint-config-egg$ tnpm i eslint eslint-config-egg babel-eslint -D# 或 React 项目使用 eslint-config-airbnb$ tnpm i eslint eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react eslint-config-airbnb -D
然后在项目根目录创建 .eslintrc 文件,并写入对应的配置,以 eslint-config-airbnb 为例:
.eslintrc
{"extends": "airbnb"}
接下来再安装 prettier lint-staged 和 husky:
$ tnpm i prettier lint-staged husky -D
简单介绍一下几个工具:
prettier用来优化代码格式,比如缩进、空格、分号等等husky用于实现各种 Git Hook。这里主要用到pre-commit这个 hook,在执行 commit 之前,运行一些自定义操作lint-staged用于对 Git 暂存区中的文件执行代码检测
接下来配置 package.json:
"scripts": {"lint": "eslint . --ext .js","prettier": "prettier --trailing-comma es5 --single-quote --write '**/*.{js,json,md}'",},"husky": {"hooks": {"pre-commit": "lint-staged"}},"lint-staged": {"**/*.js": ["prettier --trailing-comma es5 --single-quote --write","eslint","git add"]},
scripts
lint检测 js 代码的 eslint 错误prettier使用 prettier 优化代码的格式
如果一个项目之前没有使用过 linter,现在加上了,并且需要处理所有的代码格式,就可以使用 tnpm run prettier。
--trailing-comma es5 表示使用 ES5 支持的拖尾逗号;--single-quote 表示使用单引号。prettier 的所有参数详见 https://prettier.io/docs/en/options.html。
这些参数即可以在命令中配置,也可以使用配置文件 .prettierrc 来指定,如:
{"singleQuote": true,"trailingComma": "es5"}
在优化代码格式的时候,有些文件不需要进行处理,则可以通过 .prettierignore 文件来配置:
dist/node_modules*.logrunlogs/coverage/
husky
husky 里面定义了一些 Git 的钩子。
上面的示例中,"pre-commit": "lint-staged" 的含义就是在 pre-commit 阶段(也就是 commit 之前)执行 lint-staged 命令。
lint-staged
如上所述, lint-staged 在 pre-commit 的时候执行。lint-staged 里面定义了需要对 Git 暂存区中的文件执行的任务。
在该 package.json 示例中主要有一个任务: **/*.js, 即对暂存区中所有 js 文件依次执行下面的操作:
prettier --trailing-comma es5 --single-quote --writeeslintgit add
也就是先优化暂存区中的 js 代码格式,再进行 eslint 检测,最后再执行 git add,将优化后的代码添加到暂存区。暂存区中的代码文件,就是这几个命令的参数。
如果 eslint 步骤抛错了,则表示代码格式不符合 eslint 规范,进而导致 pre-commit 这个钩子就会抛错,最终导致 commit 操作失败。
因为 eslint 也只会检测 lint-staged 中的代码,也就是自己修改过的代码。所以即避免了影响他人代码,同时也避免了因他人代码格式问题造成自己的代码不能提交。
其他
husky 和 lint-staged 配合起来还有非常多的用处。
比如删除已经被 Git 追踪的文件。
比如 run/ 目录是代码运行时生成的目录。如果一开始没有将 run/ 添加到 .gitignore 里面,则每个人提交代码的时候都会提交自己的 run/ 目录。由于每个人 run/ 目录里面的文件很可能不一致,所以很容易造成冲突。
而且一旦文件已经被 Git 追踪,再将其添加到 .gitignore 里面,也无法在提交的时候忽略它。
这个时候,就可以在 pre-commit 阶段,利用 "lint-staged" 的任务删除暂存区里面的 run/。
如下所示:
"lint-staged": {"**/*.js": ["prettier --trailing-comma es5 --single-quote --write","eslint","git add"],"run/*": ["git rm --cached"]},
然后再在 .gitignore 里面添加上 run/,这样以后再提交代码的时候,就再也不会将 run/ 提交到 Git 仓库了。
