nodejh/nodejh.github.io

使用 husky+lint-staged+prettier 优化代码格式

nodejh opened this issue · 5 comments

使用 husky+lint-staged+prettier 优化代码格式


背景

团队协作中经常遇到这样的问题:

  1. 代码风格不统一

可以使用 linter 使代码风格统一。

  1. 使用 linter 检测之后有非常多的格式问题,手动修改很麻烦

可以使用 linter 命令来修复错误。比如 eslint 就可以 eslint --fix

  1. 使用命令修复的时候,不小心修改了他人代码,很容易造成冲突。

  2. 如果一个项目以前没有用过 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-stagedhusky

$ 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
*.log
run
logs/
coverage/

husky

husky 里面定义了一些 Git 的钩子。

上面的示例中,"pre-commit": "lint-staged" 的含义就是在 pre-commit 阶段(也就是 commit 之前)执行 lint-staged 命令。

lint-staged

如上所述, lint-stagedpre-commit 的时候执行。lint-staged 里面定义了需要对 Git 暂存区中的文件执行的任务。

在该 package.json 示例中主要有一个任务: **/*.js, 即对暂存区中所有 js 文件依次执行下面的操作:

  • prettier --trailing-comma es5 --single-quote --write

  • eslint

  • git add

也就是先优化暂存区中的 js 代码格式,再进行 eslint 检测,最后再执行 git add,将优化后的代码添加到暂存区。暂存区中的代码文件,就是这几个命令的参数。

如果 eslint 步骤抛错了,则表示代码格式不符合 eslint 规范,进而导致 pre-commit 这个钩子就会抛错,最终导致 commit 操作失败。

因为 eslint 也只会检测 lint-staged 中的代码,也就是自己修改过的代码。所以即避免了影响他人代码,同时也避免了因他人代码格式问题造成自己的代码不能提交。


其他

huskylint-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 仓库了。

xdlrt commented

这个挺好用的,用了一段时间了

@xdlrt 👍 我也觉得

感谢 今天用到

请问你的终端视如何左右分屏的呢?

@jackchoumine iTerm2,cmd+d 就可以分屏