Fork me on GitHub

一套完整的代码规范需要什么

  简单来说就是一系列配置项约束的集合:.editorconfig.eslintrc.prettierrcgit hooks

EditorConfig

  我们知道不同的开发人员对 IDE 的使用偏好都有差别,但是一些缩进类的配置都是共通的,一套代码我们肯定不希望在开发 A 那里是 2 个空格的 tab,跑到开发 B 那边就变成了 4 个空格的 tab。一方面你配置的prettier或者eslint可能会 ⚠️,另一方面 git 检测也会认为是 diff。

  所以有了 EditorConfig,它通过在项目中直接配置.editorconfig,可以保证缩进方式、缩进长度、换行、编码等的一致性。

  根据EditorConfig 官方的说法,大部分 IDE 本身就支持对.editorconfig配置文件的支持。我们仅需创建并编辑我们的规则即可。

  EditorConfig 会自上而下寻找对应的.editorconfig配置,所以理论上你可以配置多个,并且离当前目录树最近的一级配置文件具有最高的优先级。

  当然我们一般都是在主入口层级配置一个统一的。另外这个文件要么放在项目根目录要么在配置文件中编写root=true

  至于配置方式在官网上有 Example 说明,不过作为 FE dev,看下业内的库可能更直观,就拿jquery的配置来说:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# This file is for unifying the coding style for different editors and IDEs
# editorconfig.org

root = true

[*]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[package.json]
indent_style = space
indent_size = 2
  1. indent_style用来设置缩进的类别,有tabspace两种选择。
  2. indent_size是当我们选择indent_style = space时,才配置该属性,描述的是单位缩进的列数。
  3. tab_width是当我们选择indent_style = tab时对应的单位缩进的列数。
  4. end_of_line为换行时选择的换行符,有lfcrcrlf三种选择。一般开源的库都选择lf,linux、os x,max os 使用lf,win 使用crlf。(逼乎上有讨论说cr在 linux 类系统下问题很大,但是 win 中不用cr不会有很大问题,emm🤷‍♂️
  5. trim_trailing_whitespace置为true,会将每行后面多余的空格移除,false则会保留。
  6. insert_final_newline置为true,会在保存文件后在文件末尾新增一个空白行,false则不会。
  7. charset,字符编码,通常使用utf-8

  以上是配置,本人使用的 IDE 是 VS Code,我要怎么使这些配置生效呢?

  • Extensions安装插件EditorConfig for VS Code插件。
  • 在当前文件选取内容,快捷格式化操作 mac: ⌥ + ⇧ + F, win: alt + shift + F

ESLint

  之前也写过一篇关于 ESLint 配置的文章,见《关于 ESLint》

  ESLint 提供了一套潜在问题和写法的纠错机制,它根据一些定制逻辑会提供开发者对应的错误和警告。

  我们一般可以通过 CI 生成一份初始化 ESLint 文件:

  • npm i -g eslint,安装全局 CI,可能要使用root权限。
  • eslint --init根据命令行提示,选择我们需要的初始化配置。

  比如我根据我在浏览器环境生成了一份json格式的初始配置文件,配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"env": {
"browser": true,
"es2021": true
},
"extends": ["eslint:recommended", "plugin:react/recommended"],
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": ["react"],
"rules": {}
}

  可以看到env就是我们所处的 js 宿主环境;extends则会去继承相关eslint的配置规则,数组格式后面的配置项内的重复类型规则会覆盖之前的;parserOptions主要告诉编译器将源代码转成什么内容格式的AST进行规则分析和处理;plugins可以理解为自定义的 ESLint 检测,通常是一些比较细节的定制化扫描,其中的插件会挂载到校验环境中,并在rules中提供细节开关指定使用;rules中还支持我们额外的单条检测的定制处理。

Unexpected lexical declaration in case block(no-case-declarations)

  在个人项目执行规范时,有个小插曲,即报了Unexpected lexical declaration in case blockerror类校验提示。

  定位后发现是switch...case...语句中,分支条件代码块中进行了变量声明,但未使用{}包裹该代码块。

  这样操作会有潜在风险,因为在整个switch...case...中,我们的变量都声明在同一个上下文内,所以如果不用{}包裹,对一个变量名的声明会导致重复声明抛错:Uncaught SyntaxError: Identifier xxx has already been declared,也就意味着不同条件分支都可能会重新对其进行赋值,产生副作用。

  举些 🌰:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
switch (1) {
case 1:
let foo = 1;
break;
case 2:
let foo = 2;
console.log(foo); // 会报错:Uncaught SyntaxError: Identifier 'foo' has already been declared
break;
}

switch (2) {
case 1:
function f() {
console.log('???');
}
break;
case 2:
f(); // 会输出:???
break;
}

一些依赖的插件

  如果使用了css-modules,并希望得到一些是否引用其中样式的检测,需要安装插件eslint-plugin-css-modules

Prettier

  前面我们进行了 EditorConfig 和 ESLint 的讨论,它们的职能分别对应IDE 编辑风格规范代码问题及风格的检测规范

  而Prettier它不具备任何代码规范的纠错能力,它只是一个风格上的统一工具,这里的风格指的是类似每行代码结尾是否需要;、字符串使用单引号还是双引号包裹,最后的变量引入或者声明是否补,等问题。

  我们可以直接在项目下创建.prettierrc文件进行配置,配置文档见Options

1
2
3
4
5
6
{
"semi": false,
"useTabs": false,
"singleQuote": true,
"trailingComma": "es5"
}

  package.json下也要在devDependencies依赖下安装对应 Prettier 依赖:

1
npm i -D prettier eslint-plugin-prettier eslint-config-prettier

  安装后,还要在之前的.eslintrc.json下的plugins数组中添加prettier,注意prettier要放在插件的最后一个。

  然后我们还要像前文中描述的,在rules下手动激活prettier插件中的配置项,error表示该插件规则命中时会在控制台报错:

1
2
3
4
5
6
7
8
9
{
"extends": [
"prettier"
],
"plugins": ["prettier"],
"rules": {
"prettier/prettier": "error",
}
}

  P.S.此处的写法可以省略并简化成extends中的一句:

1
2
3
{
"extends": ["plugin:prettier/recommended"]
}

  最后同样要在Extensions中安装Prettier - Code formatter插件。

Git Hooks

  原理是利用git的hooks能力,在提交前应用我们的校验规则。

  比较主流的做法是使用huskylint-staged,前者会将其配置集成到git hooks下的pre-commit阶段并在提交前校验。后者则是限制应用范围。

  对于一个大型项目而言,代码量是非常巨大的,如果我们贸然使用前文中的prettier之类的进行格式化,会造成大量的文件变更,这样的commit会引起很多不必要的麻烦(如修改了历史提交人信息、造成code review人员额外的工作负担等),所以通过lint-staged会使规则只在我们最新的提交内容内生效,因此缩小了影响范围。

  要应用肯定得先进行安装:

1
npm i -D husky lint-staged

  在package.json中配置:

1
2
3
4
5
6
7
8
9
10
11
12
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.js": [
"eslint --fix",
"prettier --write",
"git add"
]
},

  此时当我们进行git commit -m "xxx"代码提交时,就会按照以下顺序处理代码内容:

  1. 检视所有更改的代码内容,此处只进行js后缀格式内容扫描。
  2. 先使用eslint进行修复。
  3. 使用prettier进行代码风格统一。
  4. 将变动内容重新应用进缓冲区。

Web Hooks

  实际上前文中讨论的校验规则都是在开发者本地配置的,有很多方式可以绕开(--no-verify、剔除git hooks等)。

  如果有强要求规范,可以将这些规则上到服务端。通过配置web hooks,可以在服务端拒绝我们的不符合规范的提交内容。