自动检查代码

为什么需要自动检查代码

只要是人就有疏忽的时候,何况在一个复杂的项目流程中,要进行代码检查、格式化、单元测试等种种操作,实现自动化可以大大减少由于人为疏忽导致的代码质量问题

huksy

一个功能开发完成总归有一个提交代码的操作,husky 就允许开发者在特定的 git 操作发生之前自动运行指定的脚本,这些脚本就负责执行保证代码质量的操作

安装依赖

pnpm add --save-dev husky

初始化

pnpm exec huksy init

这样根目录下就多一个一个 .husky 文件夹,要执行的脚本都放在这里面

下面就以使用 eslint 对代码进行静态分析为例子

创建 .husky/pre-commit hook,这个 hook 会在执行 git commit 后触发,可以在这个 hook 下添加代码静态分析的脚本,还有很多 hook

#!/bin/sh
pnpm exec eslint --fix .

#!/bin/sh 特殊注释行,使用指定 shell 解释器执行脚本,加上了 vscode 里才有 shell 脚本的图标

这样执行 git commit 后会自动对当前文件夹的文件进行静态分析

检查提交信息

为什么需要检查提交信息

保证提交信息整洁一致,利于快速理解提交内容的目的

commitlint

安装依赖

pnpm add --save-dev @commitlint/{cli,config-conventional}

.commitlintrc.cjs 中配置

module.exports = {
  extends: ['@commitlint/config-conventional']
}

配置 husky

.husky/commit-msg

#!/bin/sh
pnpm exec commitlint --edit $1

--edit 指定一个提交信息文件来进行检查,比如:

commitlint --edit .git/COMMIT_EDITMSG

$1 表示脚本接收到的第一个参数,在 husky 的 commit-msg hook 指的就是 .git/COMMIT_EDITMSG

规范

  • feat 增加新功能
  • fix 修复问题/BUG
  • style 代码风格相关无影响运行结果的
  • perf 优化/性能提升
  • refactor 重构
  • revert 撤销修改
  • test 测试相关
  • docs 文档/注释
  • chore 依赖更新/脚手架配置修改等
  • ci 持续集成

自动生成提交信息

为什么需要自动生成提交信息

一个规范的提交信息包含多个部分,且某个部分的信息经常需要重复且人不一定记得住,需要一种工具实现自动生成

czg

是 commitzen 的替代方案,优点如下:

  • 没有前置配置:不需要在 package.json 的 config 中配置适配器
  • 自带 cz-git 适配器
  • 启动速度更快:不需要查找适配器
  • 更轻量

基本用法

安装依赖

pnpm add --save-dev czg

脚本

{
	"scripts": {
		"cz": "czg"
	}
}

联动 commitlint

因为自带 cz-git 适配器,可以在提交时提供更丰富的配置

.commitlinrc.js

/** @type {import('cz-git').UserConfig} */
module.exports = {
  prompt: {
    useEmoji: true
  }
}

代码静态检查

为什么需要代码静态检查?

常见的非 JavaScript 服务端语言在运行前都有一个编译的过程,在这个编译的过程中会自动检查语法和类型错误

而原生 JavaScript 在运行前不需要编译的过程,只有在浏览器运行时才能发现错误警告,这样就没办法在开发阶段及时发现问题并解决

所以静态分析指的就是在不执行代码的情况下,对代码进行自动化的检查和分析,比如语法错误

ESLint

前端最常见的静态分析工具

基本用法

安装

pnpm add --save-dev eslint@8

::: tip 值得注意的是,eslint 的最新版本为 9,从配置上和 8 有很大区别,这里用 8 演示 :::

配置脚本

{
	"scripts": {
		"lint": "eslint --fix"
	}
}

执行一下命令就会自动检查目录下所有 js 代码

pnpm lint

.eslintrc.cjs 文件中对 eslint 进行配置(也可以使用其他格式配置文件,参考官方文档)

module.exports = {
  env: {
	  browser: true,
	  es6: true
  },
  root: true,
  extends: "eslint:recommended",
};

配置

  • env: 配置 eslint 检查时涉及到的运行环境,防止不认识特定环境下才有的全局变量
  • root: 标记了 eslint 搜索配置时的停止点,eslint 检查某个文件时优先使用最近的配置文件,再向上一层搜索,同时会合并途中找到的所有配置文件,直到到达带有 root: true 的配置文件或根目录
  • extends:
    • 用于使用预设的配置,不需要手动配置,
    • 使用带有 eslint-config- 前缀的 npm 包时,可以省略前缀,
    • 有两个自带的预设 eslint:recommendedeslint:all
  • plugins:
    • 拓展非 JavaScript 语法的自定义规则
    • 自带预设配置,通过 plugin: 前缀使用
    • 使用时可以省略 eslint-plugin- 前缀
  • parser: eslint 校验代码前默认使用 Espree 解析器将 JavaScript 语法转换成 AST 后再进行校验,对于其他语法默认解析不了,因此需要其他解析器帮助

兼容 TypeScript

安装依赖

pnpm add --save-dev @typescript-eslint/eslint-plugin @typescript-eslint/parser

配置

module.exports = {
  parser: "@typescript-eslint/parser",
  extends: ["plugin:@typescript-eslint/recommended"],
  plugins: ["@typescript-eslint"],
};

兼容 Vue

安装依赖

pnpm add --save-dev eslint-plugin-vue

配置

module.exports = {
  parser: "vue-eslint-parser",
  parserOptions: {
    parser: "@typescript-eslint/parser",
  },
  extends: [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:vue/vue3-recommended",
  ],
  plugins: ["@typescript-eslint", "vue"],
};

VSCode 插件

插件可以自动读取配置文件,实现主要的两个功能:

  • 对文件进行错误高亮
  • 保存后自动修复错误

.vscode/setting.json

{
	"editor.codeActionsOnSave": {
		"source.fixAll.eslint": "explicit"
	}
}

格式化代码

为什么需要格式化代码

统一团队的代码格式,一定程度上提升了可读性,也避免因为提交时因为格式不一致导致提交内容包含太多无关的格式化变更

prettier

基本用法

安装依赖

pnpm add --save-dev prettier

.prettierrc.cjs 中配置

module.exports = {
  semi: false,
}

脚本

{
	"scripts": {
		"format": "prettier --write"
	}
}

兼容 eslint

安装依赖

npm install --save-dev eslint-plugin-prettier eslint-config-prettier

配置

.eslintrc.cjs

module.exports = {
  extends: [
    "eslint:recommended",
    "plugin:prettier/recommended",
  ]
}

plugin:prettier/recommended 自动关闭 eslint 和风格有关的规则,自动配置了 eslint-plugin-prettiereslint-config-prettier

plugin:prettier/recommended 放到数组最后一个保证可以覆盖前面的规则

VSCode 插件

安装插件

配置保存自动格式化(似乎配置文件命名要以 .prettierrc 才行,不过如果成到 eslint 中就不需要了)

.vscode/settings.json

{
	"editor.defaultFormatter": "esbenp.prettier-vscode",
	"editor.formatOnSave": true
}

检查暂存区

为什么需要检查暂存区

在利用 husky 检查时,默认是对全部文件进行检查,不管文件是否有变更,产生了多余操作,导致检查速度变慢,进而导致提交速度变慢,我们知道要提交更改的文件都放在暂存区,那么只需要检查暂存区中的文件即可

lint-staged

会匹配暂存区中对应格式的文件进行对应检查

安装

pnpm add --save-dev lint-staged

pacakage.json 中配置

{
    "lint-staged": {
        "*.{js.ts}": "eslint --fix"
    }
}
  • key 是匹配对应文件的语法
  • value 是对匹配文件的检查命名

配置到 hook 上

#!/bin/sh
pnpm exec lint-staged

故障排除

.eslintrc.cjsmodule 语法报错

因为 eslint 不确定当前文件的运行环境,.eslintrc.cjs 应该在 node 环境下被读取,所以对该文件指定环境为 node 环境,配置文件顶部加上这句

/* eslint-env node */

为什么没有配置 @typescript-eslint/parser 的情况下也能校验 ts 语法?

可能是 ts 代码过于简单,导致使用默认解析器解析出来的内容和 js 类似?不过不配置预设的情况下,肯定校验不了,这时候就一定要加上 @typescript-eslint/parser 解析器