上一篇讲了如何使用 TS + Rollup + Jest 创建开发环境。本文和大家分享如何提高代码的规范和质量,让多人协同变得更高效。成品可以参考 utils ,欢迎 star 🤞❤️
ESLint + Perttier 代码规范配置
关于 ESlint 的项目搭建,可以参考 ESLint 非权威配置指北(下),代码规范几乎每个项目都会配置,这里就不再赘述。
最终,我们添加了 .eslintrc.js
、.eslintignore
、.prettierrc.js
配置文件,并且添加了以下两条 Scripts 命令:
{
"scripts": {
"lint:eslint": "eslint --cache --max-warnings 0 \"packages/**/*.{js,ts}\" --fix",
"lint:prettier": "prettier --write \"packages/**/*\""
}
}
还有一个与 TS 相关的 ESLint 问题,值得拿出来讨论下,请看 FAQ。
FAQ
1. ESLint was configured to run ... However, that TSConfig does not / none of those TSConfigs include this file"
这些错误是由 ESLint 配置请求类型信息引起的,因为在 tsconfig.json
中并未包含 ESLint 的配置文件,所以 TS 并没有对这些文件起作用。
如果你想关闭该错误提示,可以直接在 .eslintignore
中进行忽略,也可以做如下两步操作,解决报错:
-
项目目录下新建
tsconfig.eslint.json
文件(与其他 TS 配置区分),将所有配置文件包含进去。{ "compilerOptions": { "types": ["@types/node"], "noEmit": true, "allowJs": true }, "extends": "./tsconfig.base.json", "include": [ ".eslintrc.js", ".prettier.js", "rollup.config.js", "jest.config.js", "babel.config.js", ] }
-
接着,在
.eslintrc.js
中提供 TS 配置文件的路径。所有需要使用类型信息的规则,都要在此配置:module.exports = { /** ...... */ parserOptions: { /** ...... */ project: ['./tsconfig.base.json', './tsconfig.eslint.json', './tsconfig.json'], tsconfigRootDir: __dirname, }, }
关于该报错的详尽信息,可以查阅 ESLint was configured to run ...。
关于 ESLint parserOptions.project
选项的说明,可以查阅 project。
关于官方的解决方案示例,可以查阅 tsconfig.eslint.json。
配置 Editorconfig
editorconfig 也是用来帮助开发者定义和维护代码风格的。但是它与 Prettier 不同的是,Prettier 是 JS 特有的格式化工具,里面有很多配置项是 JS 语言特有的规范,而 editorconfig 适应性更广泛,它可以跨编辑器(或 )维护统一的代码风格,专注于比较基础的格式化,比如 Tab 缩进、文件编码、末尾换行符等,这些规范与使用哪种编程语言无关。
VSCode 需要安装 EditorConfig 扩展来搭配使用,部分配置如下:
# .editorconfig
root = true
[*]
charset = utf-8
indent_style = space # 空格缩进
indent_size = 4 # 缩进空格为4个
end_of_line = lf # 文件换行符是 linux 的 `\n`
insert_final_newline = true # 文件末尾添加一个空行
trim_trailing_whitespace = true # 不保留行末的空格
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false
max_line_length = 0 # 在指定的字符数后强制换行。off 关闭此功能
[package.json] # 对 package.json 生效
indent_size = 2
husky + lint-staged + commitlint 提交规范配置
git hooks 前置知识
和其它版本控制系统一样,Git 能在特定的重要动作发生时触发自定义脚本。
有两组这样的钩子:客户端的和服务器端的。 客户端钩子由诸如提交和合并这样的操作所调用,而服务器端钩子作用于诸如接收被推送的提交这样的联网操作。
你可以随心所欲地运用这些钩子。
本文整理部分 hooks 如下:
git hooks | 运行时机 | 说明 | 工作流 | 所属类型 |
---|---|---|---|---|
pre-commit | 在键入提交信息前运行 | 以非零值退出,Git 将放弃此次提交, 可以利用该钩子,来检查代码风格是否一致 | 提交 | 客户端 |
prepare-commit-msg | 在启动提交信息编辑器之前,默认信息被创建之后运行 | 提交 | 客户端 | |
commit-msg | 接收一个参数, 以非零值退出,Git 将放弃提交。可以在提交通过前验证项目状态或提交信息 | 提交 | 客户端 | |
post-commit | 在整个提交过程完成后运行 | 一般用于通知之类的事情 | 提交 | 客户端 |
applypatch-msg | 可以用该脚本来确保提交信息符合格式,或直接用脚本修正格式错误。 | 客户端 | ||
pre-applypatch | 运行于应用补丁之后,产生提交之前 | 可以用它在提交前检查快照 | 客户端 | |
post-applypatch | 运行于提交产生之后 | 可以用它把结果通知给一个小组或所拉取的补丁的作者 | 客户端 | |
pre-rebase | 运行于变基之前 | 可以使用这个钩子来禁止对已经推送的提交变基 | 其他 | 客户端 |
post-rewrite | 被那些会替换提交记录的命令调用 | 用途很大程度上跟 post-checkout 和 post-merge 差不多 | 其他 | 客户端 |
post-checkout | 在 git checkout 成功运行后 | 可以根据你的项目环境用它调整你的工作目录 | 其他 | 客户端 |
post-merge | 在 git merge 成功运行后 | 可以用它恢复 Git 无法跟踪的工作区数据 | 其他 | 客户端 |
pre-push | 会在 git push 运行期间, 更新了远程引用但尚未传送对象时被调用 | 可以在推送开始之前,用它验证对引用的更新操作 | 其他 | 客户端 |
pre-auto-gc | 会在垃圾回收开始之前被调用 | 可以用它来提醒你现在要回收垃圾了,或者依情形判断是否要中断回收 | 其他 | 客户端 |
pre-receive | 客户端的推送操作时,最先执行 | 可以用这个钩子阻止对引用进行非快进(non-fast-forward)的更新,或者对该推送所修改的所有引用和文件进行访问控制 | 推送 | 服务端 |
update | 会为每一个准备更新的分支各运行一次 | 更新 | 服务端 | |
post-receive | 在整个过程完结以后运行 | 可以用来更新其他系统服务或者通知用户 | 完结 | 服务端 |
这里,我们通常只关注提交工作流的几个 hooks,用的最多的一个就是 pre-commit
。当然,你可以利用 git commit --no-verify
来绕过这个环节。
配置 husky
Husky 就是一个创建或修改 Git hooks 的工具,它在内部封装了 git hook,允许我们在提交代码时运行一些额外的脚本。比如校验规范,格式化代码等。
初始化 husky
执行 npm i husky -D
安装 Husky 后,我们在 package.json
中添加一个 script:
{
"scripts": {
// ......
"prepare": "husky install"
}
}
执行 npm run prepare
,会创建 .husky
文件夹,此时 git hook 已被启用。
创建 git hook
接着,我们使用 husky add <file> [cmd]
命令往里面添加 hook,其中:
- <file>: 指名为 git hook 的文件,通常放在
.husky/
目录下。比如:.husky/pre-commit
; - [cmd]: 指想要运行的命令。比如:
npm run lint:eslint
。
以下是官方示例:
npx husky add .husky/pre-commit "npm run test"
git add .husky/pre-commit
此时,.husky 文件夹中会创建一个名为 pre-commit
的 shell 脚本。当你尝试 commit 提交时,pre-commit
hook 会提前执行其中的 npm run test
,如果检测失败,那么本次提交会被自动阻止。
当然,你可以根据自己的需求修改这个 shell 脚本。
官方推荐
typicode.github.io/husky/get-s…
我们还可以使用官方推荐的方法,一次性快速初始化 husky 。
# npm
npx husky init
# pnpm
pnpm exec husky init
该命令会自动初始化并生成 pre-commit
脚本,我们只需直接去里面修改内容即可,很方便。
配置 lint-staged
这里有个问题:npm run lint:eslint
会对你自定义的所有文件进行 ESLint 修改,成本显然很高。
所以 lint-staged 的出现允许你每次 commit 时只对当前添加到暂存区(stage)的代码进行 lint,效率大大提高。正如它的标题:不要让屎溜进你的代码库!
lint-staged 的配置方式有两大种,支持 package.json
或 JSON 和 YML 风格的 .lintstagedrc
。
我们以 package 为例,在执行 npm i lint-staged -D
安装依赖后,在 package.json
中添加 lint-staged
字段,格式如下:
{
"lint-staged": {
"<glob-pattern>": "<command>"
}
}
其中 <command> 可以是原生的工具库命令,也可以是 Scripts 里的自定义命令。原生命令可以省略 npm run
前缀,但自定义命令必须是完整的,比如 eslint --fix
和 npm run lint:eslint
。
命令的类型可以是单个命令的字符串,也可以多个命令组成的数组。
{
"lint-staged": {
"packages/**/__tests__/*.ts": "npm run test",
"packages/**/*.ts": [
"npm run lint:eslint", // scripts 自定义的命令
"prettier --write" // prettier 原生的命令
]
}
}
上述 lint-staged 我们配了两个操作:
- 所有 packages 下的单元测试文件在提交前,都要执行 jest 测试;
- 所有 packages 下的 .ts 文件都要执行 eslint 校验以及 prettier 格式化。
不过目前它还不能自动生效,要在 .husky/pre-commit
脚本中修改并添加 npx --no-install lint-staged
命令,这样就生效了。
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
echo -e "\033[33m ------------------- 正在对提交的代码执行操作 -------------------- \033[0m"
npx --no-install lint-staged
配置 commitlint
commitlint 用来约束提交信息,规范提交格式。
-
安装
npm i @commitlint/config-conventional @commitlint/cli -D
-
自定义 commitlint.config.js 规范
module.exports = { ignores: [commit => commit.includes('init')], extends: ['@commitlint/config-conventional'], rules: { 'body-leading-blank': [2, 'always'], // 主体前有空行 'footer-leading-blank': [1, 'always'], // 末行前有空行 'header-max-length': [2, 'always', 108], // 首行最大长度 'subject-empty': [2, 'never'], // 标题不可为空 'type-empty': [2, 'never'], // 类型不可为空 'type-enum': [ // 允许的类型 2, 'always', [ 'wip', // 开发中 'feat', // 新增功能 'merge', // 代码合并 'fix', // bug 修复 'test', // 测试 'refactor', // 重构 'build', // 构造工具、外部依赖(webpack、npm) 'docs', // 文档 'perf', // 性能优化 'style', // 代码风格(不影响代码含义) 'ci', // 修改项目继续集成流程(Travis,Jenkins,GitLab CI,Circle等) 'chore', // 不涉及 src、test 的其他修改(构建过程或辅助工具的变更) 'workflow', // 流水线 'revert', // 回退 'types', // 类型声明 'release', // 版本发布 ], ], }, };
-
使用 husky 继续添加
commit-msg
git hook:npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
现在,你的 .husky 目录应该长这样:
你可以使用 git add . && git commit -m'aaa: bbb'
来测试了,正常会出现报错。
总结
- ESLint 和 Prettier 配置;
- Editorconfig 的配置;
- Git hooks 与 Husky;
- lint-staged 的配置;
- FAQ 问题梳理;
下篇将分享如何为我们的 README 添加 badge 徽章,以及重头戏:白嫖 Github Actions 实现一个简单的 CI/CD 来部署并自动发布 NPM。
往期文章
《从零开发自己的工具库(一)配置 TS + Rollup + Jest》
《从零开发自己的工具库(三)配置 Github Actions CI 自动发布 NPM》