使用Prettier,Husky和lint-staged,在提交javascript代码前自动格式化代码

目标

为防止提交不合格的代码排版到仓库中,我们希望在提交前格式化代码,使之符合项目的代码格式规范,而且尽可能保证逻辑正确。即目标有两点:
1. 对git staged的代码强行格式化,使符合规范。对于没有被staged的代码或文件,将完全忽略。
2. 跑单元测试。只有通过了单元测试才能提交代码。

安装依赖

$ npm install --save-dev husky lint-staged

先安装husky和lint-staged。注间在安装husky之前需要确保工程目录已经是一个合法的git仓库。因为,安装husky时需要给git仓库安装预提交钩子(precommit hook)。
Lint-staged提供了一个关键的功能,它能找到所有被git staged的文件,而不是工程下面所有的文件,然后通过管道交给Prettier做格式化。

修改npm脚本

对npm script做如下改动:

  "scripts": {
    "precommit": "lint-staged"
  },
  "lint-staged": {
    "*.{js,jsx,json}": ["prettier --write", "git add"]
  }

scripts.precommit由Husky处理,它会依照配置在把代码正式提交到仓库前运行lint-staged(当然我们也可以配置其他命令)。
Lint-staged再找到属于它自己的配置部分,即lint-staged键下面的配置。
在此例中,所有staged状态的,且扩展名是.js, .jsx, 和.json文件都会自动交由Prettier做格式化,然后再提交。

为何一定要用lint-staged

You might wonder why we don’t just use Husky to run a few npm scripts.
你可以会疑惑,为什么一定要罗里罗嗦地用lint-staged,用Husky直接调用npm脚本不更简单么。
这是因为我们用lint-staged拿到staged状态的文件,而不是所有的文件。
你的node工程文件中可能已经有如下做代码格式化的脚本

"format": "prettier --write '**/*.{js,jsx}'"

你可能会因此如下配置

"lint-staged": {
  "*.{js,jsx,json}": ["npm run format", "git add"]
}

如果是这样配置的话,就没有必要用lint-staged了。因为,这样的配置会把prettier应用到所有匹配.js,.jsx.json的文件上,而不是仅staged状态的文件。

把跑单元测试加入预提交检查

Husky还能够帮你把跑单元测试加入到预提交检查中,保证只有通过了单元测试才正式提交代码到仓库。
如下是一个典型的配置:

"scripts": {
    "test": "exit 0",
    "precommit": "lint-staged && npm test"
  },
  "lint-staged": {
    "*.{js,jsx,json}": ["prettier --write", "git add"]
  }

实际项目中要修改scripts.test部分,视工程使用的单元测试框架Jest, 或Mocha ,本示例简单的返回0,表示无条件通过。