注意事项
本文默认开发环境是 VSCode,团队内尽可能统一开发环境,避免编辑器差异、插件不兼容的问题。
以下提到的工具核心都是配置文件,并且这些配置文件通常都能通过多种格式配置,例如 .js
、.yaml
、.json
或者直接在 package.json
中配置。后面不再赘述相关设定,具体配置形式可以在官方文档查询,本文仅解析部分配置项目。
代码风格
代码风格一致是项目协作的基石,使用 ESLint 和 Prettier 可以避免由于代码格式不一致带来的代码合并冲突,也可以提高代码可读性和可维护性。虽然在认识 ESLint 和 Prettier提到过,但是下面想要作为升级版讲得更完整一点。
ESlint
本文介绍的第一个工具是 ESlint,其功能是:
- 提供代码规范,例如:建议你使用
===
而不是==
,建议你未修改过的变量使用const
而不是let
等这样的规则 - 其次是格式化代码,控制缩进换行之类的问题
安装
VSCode 插件
在项目中安装了 ESlint 确实提供了文件校验和整理的接口,但实际上在写代码过程中格式化总不能每次都自己调一下 api 处理当前文件,这个时候就需要使用 ESlint 插件。安装插件后可以通过快捷键调用 eslint api 处理当前文件,甚至在保存时自动格式化当前文件,在编码窗口也会使用黄线和红线标注警告和错误代码。
安装完 ESlint 本体和 VSCode 插件你可以使用一些基本功能,但要与 React、Vue、TS 等文件配合使用需要安装相应插件(注意这里说的是 ESlint 的 plugins,跟前面提到的 VSCode 插件没有关系),后面会详细介绍插件(plugins)相关问题。
配置
先看一眼 ESlint 的配置文件,它用于配置和扩充 ESLint 规则,这是一个例子:
接着详细解析一下 extends、plugins、rules 三个配置。
Extends
上面提到的规则有一两百条,要每条手动配置不现实,我们可以使用 Extends。
Extends 是配置的集合,添加了 Extends 等于添加了一组配置。配置 extends 的值时可以忽略包名的 eslint-config-
前缀。
很多大厂都有自己的一套规范,例如前端代码规范领域著名的 airbnb,他们的配置文件是 eslint-config-airbnb,安装之后使用时只需要这么写:
不过……其实个人建议用 eslint:recommended
或者 standard
而不是 airbnb
,因为 airbnb 实属管太多,例如 no-plusplus
和 no-underscore-dangle
正常使用并没有什么问题,他也给开了,跟原来的编码习惯差距比较大所以选择不用了 😂。
当然,配置集合还有其他选择,例如 eslint-config-alloy;你还可以发布自己的配置集合,其实这也是官方推荐的做法。
Plugins
Plugins 比 Extends 更强劲,不止可以补充配置,更能新增 ESLint 自定义规则。配置 plugins 的值时可以忽略包名的 eslint-plugin-
前缀;因为 plugin 中也可以包含配置集合,使用 plugin 中的配置集合时可以使用plugin:包名/配置名
的格式,如 plugin:vue/essential。
在安装 eslint-plugin-vue 之后可以这样添加插件,就能在 ESLint 中新增一大堆 Vue 的规则(注意只是新增规则,并未配置规则是否使用):
各种语言详细的配置这里就不一一赘述了,eslint-plugin-xxx
的文档一般会提供比较完善的帮助。
Rules
在 extends 添加完规则集合之后,很可能还要根据自己习惯微调一些规则,这时候就可以在 rules
配置一些单条规则。
规则的等级有三种:
- “off” or 0 - turn the rule off
- “warn” or 1 - turn the rule on as a warning (doesn’t affect exit code)
- “error” or 2 - turn the rule on as an error (exit code is 1 when triggered)
配置方式大概长这样(一些特殊规则会有其他配置项,可以在规则对应页面获取相关信息):
其他问题
配置未生效:
在更新完 .eslintrc
却发现新配置在 VSCode 没有生效时,可以通过 ctrl shift P 然后选 Reload Window
快速重启 ESlint 插件。
VSCode 保存时自动格式化配置,修改 settings.json
:
Prettier
Prettier 是一个现代化的代码格式化工具。相比 ESLint,它专注于代码格式化,可以处理多种语言,包括 JavaScript、CSS、SCSS、markdown、yaml 等。Prettier 补全了 ESLint 只处理 js 系文件的问题,但对于 js 这个两者皆可处理的交集,仍然需要一些额外的兼容操作。
安装
注意一定要加 --save-exact
,因为不同版本的 prettier 处理某些格式时会有差异,为了保证团队全员格式相同,必须统一 prettier 版本。
VSCode 插件
原理跟 ESLint 一样,npm 安装只提供 api,安装 VSCode 插件才能在编辑器方便格式化。
配置
By far the biggest reason for adopting Prettier is to stop all the ongoing debates over styles.
Prettier 为了让大家少在格式上争吵,只提供了少数配置项,这样大家只要在这几个项目中争吵就可以了(误)。下面这些是 Prettier 几乎全部配置,文件名为 .prettierrc
:
ESlint 兼容
之前有在用 eslint 和 prettier 让跨 IDE 协作更舒服提到可以手动让 ESlint 和 Prettier 兼容,不过那只是因为使用不同编辑器方便同步的一种方法,这里再介绍一下用 ESlint 插件兼容的方法。
要完整使用 ESLint 接替 Prettier 的工作需要 eslint-plugin-prettier。它的原理是使用 eslint-config-prettier 仅关闭所有 prettier 相关规则,然后通过插件把 Prettier 的规则转到 ESlint 一起校验。要做到上述全部操作只需要下面一行配置:
因为配置 "extends": ["plugin:prettier/recommended"]
后相当于填充了以下一组配置:
其他问题
特殊规则:
注意 prettier 覆盖了的一些特殊规则,例如会默认关掉 vue/html-self-closing
等规则,请再另外根据自己需求再 rules
配置。
提交门禁
以上是统一代码格式相关的工具,但没有保证提交到代码库的代码经过格式化,使用 husky 可以在提交前对代码检查,保存提交的代码符合团队规范。
Husky
Git hooks made easy 🐶 woof!
husky 为 npm 项目提供介入 Git hook 的能力,它支持所有 Git hook,但我们一般只会用到 pre-commit
和 commit-msg
。
pre-commit
用于提交前的检查,commit-msg
用于提交信息检测。
无法使用 pkg
可以直接在 package.json
配置:
之后使用 husky add <file> [cmd]
的格式添加 hook 触发的命令即可,接着介绍一下在 pre-commit
和 commit-msg
分别要使用的 lint-staged
和 commitlint
。
lint-staged
Run linters against staged git files and don’t let 💩 slip into your code base!
对于新接入 ESLint 的代码库,每次提交都检测所有文件,不通过就不允许提交的话,是不是有点过分了?使用 lint-staged 可以只校验当前提交的文件,让你的项目渐进式更新代码风格。
安装
配置
配置文件名 .lintstagedrc
,因为 lint-staged 的配置比较简短,可以直接写在 package.json
的 lint-staged
对象里。
配置范例:
husky 触发
commitlint
commitlint 可以检测提交信息是否符合规范。
简单来说就是这样的格式:type(scope?): subject
,实际例子可能是这样的:feat(blog): add comment section
。详细规范可以查看理解语义化 Commit。
安装
配置
配置文件名 .commitlintrc
,配置范例:
可以在 Github 查看更完整的填写示例。
husky 触发
流畅协作
有统一的代码风格,并且确保这些规定能执行之后,下面还有一些可以让协作更流畅的工具。
Typescript
在正经地使用 TS 后,团队成员可以清楚看到每个变量的类型,包括后端接口返回的数据。不过为什么我要说“正经”使用呢,因为很多人把 TS 玩成“Anyscript”。
顺带的好处是,因为已经有类型提示,你就总会被提醒某些值有可能是 undefined
,有了这些提醒,你基本可以避免前端噩梦 Cannot read properties of undefined
。
确认,写 TS 会在最初开发的时候花费不少时间写类型,但是维护代码(甚至是别人写的代码)时得到的好处,谁用谁懂。
Storybook
storybook 是一个可以轻松展示项目内公共组件的工具,对一个组件写 story 就能脱离项目预览这个组件,并且可以自动生成 props 文档。团队可以要求成员在添加公共组件后为组件写 story,这样所有成员都可以对组件有直观的认识,减少重复造轮子的可能性。
对于大多数前端项目,直接安装并运行 storybook 就可以了。
就我最近的 Vite Vue3 项目来说十分流畅,装上基本能用,配置文件作了一点小改动,把 Vite 的 proxy 加到 viteFinal
里,以及添加 remarkGfm
插件。
包管理器
使用固定包管理器,一般选择有以下几种:
想快速了解几种管理器的差异可以查看《速通 npm、yarn、pnpm》。同时强烈推荐《JavaScript package managers compared: npm, Yarn, or pnpm?》,讲得全面且清楚,下面贴一张来自此文的性能对比图:
可以按照喜好和兼容性自行选择,但是无论选择哪个管理器,非必要时,不要删除 lock 文件!!! 在安装依赖时,管理器需要计算依赖版本,很耗时,有 lock 可以直接按 lock 列表安装。
但是有 lock 的时候,依赖的下载地址是固定的,所以配仓库会不生效,持续集成时需要注意。
P.S. 不同管理器在配 husky 的时候可能有些差异
引擎版本
如果保留了依赖的 lock 文件,那么记录当前应用适配的 node 版本也是十分必要的,不同 node 版本会造成下载的依赖不一样、甚至依赖根本不适配当前 node 版本;另外,还有一些老项目,必须用旧的 node 版本才能运行,但是接手的时候根本不知道用的那个版本,就十分让人无奈。
为解决这个问题,我们可以在 package.json
指定 node 和 npm 版本:
团队人多、项目多时,很可能出现大家版本不一样的情况,在必要时,可以使用 node 版本管理器,这里推荐三款:
- nvm unix, macOS nvm-windows Windows
- n macOS, Linux
- fnm macOS, Windows, Linux
基本上可以做到一行命令安装版本、一行命令切换版本,十分方便。
.npmrc
相信文件名带着 rc
已经很熟悉了,.npmrc
作用就是添加项目级别的 npm 配置,例如:
- 改仓库,有的公司有自己的镜像,可以在
.npmrc
配置,不用每次都在安装的时候带一串参数,也不会影响全局配置 - 还可以添加一些二进制包的下载地址,例如那个烦人的 sass
分支策略
选择一种分支策略,可以选择以下三种策略,也可以以这些策略为基础调整出一个最适合自己团队的策略:
总结
- 使用 ESlint 和 Prettier 控制代码规范和代码风格
- 添加 VSCode 插件极速格式化当前文件
- 添加提交门禁,保证上传到版本控制的代码符合规范
- 使用 husky 添加提交钩子,控制提交是否成功
- lint-staged 用于只检查本次提交文件是否符合要求,利于项目渐进式控制代码规范
- commitlint 保证提交信息可读性
- 使用 Typescript,开发时发力,维护时轻松
- 使用 Storybook 直观了解项目的复用组件
- 团队内使用统一的包管理器,保留依赖 lock 文件
- 固定引擎版本,防止依赖变化,也能避免老项目不知道使用什么版本运行的窘境
- 使用
.npmrc
固定仓库等配置 - 选择一种分支策略,使代码历史更有序
各位看完觉得有遗漏或者有什么不懂我再补充!