Appearance
在团队开发过程中需要良好的代码规范帮助我们提高团队代码协作,常见的方式就是 使用 eslint 配合 prettier 来进行代码规范的约束。具体使用可以参考 eslint 和 prettier 官网。 或者是章节中的前端工程化 / 搭建代码规范 章节中讲解
关于 vue 配置 eslint 和 prettier
在通过vite安装完成项目后,选择了 eslint 和 prettier 作为代码规范检测工具后生成两个文件 .eslintrc.cjs
和 .prettierrc.json
.eslintrc.cjs 文件
plugin:vue/vue3-essential ,这是 Vue 3 的基本 linting 规则,并且替换了默认的 JavaScript 解析器,因为 Vue.js 单个文件组件不是普通的 JavaScript,所以为了能够让语法树进行分析就需要是要vue 自己的解析器Vue-eslint-parser。 使用他首先安装
yarn add -D eslint eslint-plugin-vue
其中 plugin:vue/vue3-essential 规则主要针对 加上防止错误或意外行为的规则,但不会强制执行个人偏好的规则。如果你想要一个更严格的规则集,可以使用 plugin:vue/vue3-strongly-recommended 或 plugin:vue/vue3-recommended。查看他的规则eslint:recommended 这是 ESLint 推荐的规则集 该规则集包含一些在 ESLint 官方文档中被认为是最佳实践的规则,这些规则可以帮助你避免一些常见的错误。
@vue/eslint-config-typescript:这是 Vue 官方提供的 TypeScript linting 规则 ,它还关闭了 eslint 中的几个冲突规则: 推荐规则集,这个配置是专门为 @vue/cli & create-vue 设置而设计的,不适合外部使用(它可以使用,但可能需要在用户端进行一些修改——详细信息请参阅配置文件)。需要配合 @rushstack/eslint-patch 安装
npm add --dev @vue/eslint-config-typescript @rushstack/eslint-patch
,@vue/eslint-config-typescript
有两套规则集,一个是@vue/eslint-config-typescript
,一个就是@vue/eslint-config-typescript/recommended
。其中,后者更加严格参考规则@vue/eslint-config-prettier/skip-formatting:专门给 Vue 使用的 Prettier 验证规则(eslint-config-prettier)。作用:关闭所有不需要的、或者可能与 Prettier 产生冲突的 eslint 规则。
parserOptions:解析器选项,允许你指定 JS 语言(包括 JSX 语法),默认为 ES5。这里设置为 latest,表示支持最新的 ES 语法。
注意他们的顺序 Prettier 它应该被放在 extends 数组的最后而覆盖其他配置,这样就能完全关闭 ESLint 规则集中与格式化代码相关的规则,并且如果在 eslint 中集成了 Prettier,那么在使用 eslint fix 时候也会一并修复 prettier 的规则。
js
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
'extends': [
'plugin:vue/vue3-essential',//vue3语法规则
'eslint:recommended', //全部规则默认是关闭的,这个配置项开启推荐规则
'@vue/eslint-config-typescript', // ts语法规则
'@vue/eslint-config-prettier/skip-formatting' // 关闭eslint 和 prettier 的冲突
],
//指定解析器:解析器
//Esprima 默认解析器
//Babel-ESLint babel解析器
//@typescript-eslint/parser ts解析器
// "parser": "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: 'latest' //校验ECMA最新版本
}
}
这段代码 require('@rushstack/eslint-patch/modern-module-resolution')
问题背景在大型的 JavaScript 或 TypeScript 项目中,特别是使用了多包(monorepo)结构的项目,依赖管理可能会变得相当复杂。这种情况下,ESLint 的默认模块解析
这是一个由 Rush Stack 提供的补丁,用于改进 ESLint 的模块解析逻辑。它主要解决了两类问题:
依赖查找:在多包结构中,
node_modules
目录可能不仅仅位于项目的根目录,还可能在各个子包中也有。这个补丁改进了对node_modules
的搜索逻辑,使其能够在这种环境中更准确地解析依赖。插件和配置解析:在使用 ESLint 的过程中,你可能会引用一些第三方插件或预定义的配置。这个补丁确保 ESLint 可以正确地找到并应用这些资源,即使在复杂的项目结构中。
要使用这个补丁,你需要在项目的 ESLint 配置文件(通常是 .eslintrc.js
)的顶部添加以下代码:
javascript
require('@rushstack/eslint-patch/modern-module-resolution');
这样,当 ESLint 运行时,它会使用这个补丁改进的模块解析逻辑,而不是默认的逻辑。
这个补丁特别适用于以下几种场景:
- 使用 Yarn Workspaces 管理依赖的项目。
- 使用 Rush.js 或 Lerna 这样的多包管理工具。
- 在一个大型项目中,有多个嵌套的
node_modules
目录。
通过应用这个补丁,你可以避免因模块解析问题导致的一系列常见错误,如 "ESLint 插件未找到" 或 "配置未找到" 等。
希望这能让你对 @rushstack/eslint-patch/modern-module-resolution
有更深入的了解!有其他问题,随时问我。
具体参考
说明
在之前章节中说过 解释器 和冲突,但在项目搭建生成中并没有看到 用来解决 eslint 和 prettier 冲突的插件,这是因为在 @vue/eslint-config-prettier
依赖解决了 eslint 和 prettier 的冲突,所以在项目中不需要再次安装了。
关于vue 的解释器配置 参考在 plugin:vue/vue3-essential
配置vscode
在项目的 .vscode/settings.json
配置文件中写好了自动格式化规则,当保存时候 就可以采取 Prettier 来进行格式化
json
{
"editor.tabSize": 2,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
使用git 钩子
每个人开发环境都不同,不能保证每个人都遵守 这些提交规则,因此在实际开发中也会对 git hooks
做一些校验保证项目的规范,这里具体的可以参考git限制提交
整体可以归纳总结
安装 husky 来接管 git hooks ,直接去改动git hook是不明智因为改动本地的钩子是无法同步到远程仓库的git 钩子上因此可以使用 Husky 是一个 Git hooks 工具,它允许你在项目中配置钩子脚本
bash
npm install -D husky
初始化 husky
bash
npx husky-init
pre-commit (提交前钩子),在执行真正的提交操作之前运行的钩子当我们执行 git commit 命令提交代码时,Git会在实际进行提交操作之前触发 pre-commit 钩子,这个阶段用来检查代码将代码格式化最好阶段
但这个阶段一般只需要对暂存的文件进行格式化,因此需要 lint-staged
只检测暂存区的代码lint,会阻止提交,以便你有机会修复这些问题
bash
npm install lint-staged --save-dev
注册运行暂存检查的指令 npm pkg set scripts.lint-staged="lint-staged"
json
// change 1: 配置lint-staged指令
"scripts": {
// 新增这一行
"lint-staged": "lint-staged",
...
},
配置lint-staged的具体任务 在package.json 文件中
如果您已经在 ESLint 配置中集成了 Prettier(通过使用
eslint-plugin-prettier
和eslint-config-prettier
),那么您只需要运行eslint --fix
。这样,Prettier 的格式化规则也会被应用,无需再单独运行prettier --write
。ESLint 主要用于检查 JavaScript、TypeScript 和现代 JavaScript 框架(如 React 和 Vue)的代码。它不是设计用来检查 JSON、Markdown 或其他非-JavaScript 文件的,因此除了这类文件依旧采用的是
prettier --write
检测
json
// change 2: 配置lint-staged的具体任务
{
"lint-staged": {
"*.{js,jsx,ts,tsx,vue}": "eslint --fix",
"*.{scss,less,styl,html}": [
"stylelint --fix",
"prettier --write"
],
"{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": "prettier --write --parser json",
"package.json": "prettier --write",
"*.md": "prettier --write"
}
}
将 lint-staged
指令配置到 .husky/pre-commit
钩子中
bash
npx husky add .husky/pre-commit "npx lint-staged"
commit-msg(提交信息钩子),为了能规范大家git 提交信息这里需要使用,我们可以通过commit lint来限制提交,安装 @commitlint/config-conventional
和 @commitlint/cli
@commitlint/config-conventional
:这个包主要用于定义和配置 Conventional Commits 规范,规定了提交消息的格式和规则,但它本身不会执行验证。@commitlint/cli
:这个包是一个命令行工具,用于在 Git 提交时验证提交消息是否符合规范。@commitlint/cli
实际执行验证操作,检查提交消息是否符合@commitlint/config-conventional
中定义的规范。
shell
npm i @commitlint/config-conventional @commitlint/cli -D
安装完成后可以在 commitlint.config.js
文件,配置 commitlint ,我们告诉 commitlint 在验证提交信息时应该使用 @commitlint/config-conventional
规范配置中定义的规则
js
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
[
'新功能', // 添加新功能
'修复', // 修复 bug
'文档', // 文档变更
'样式', // 样式变更
'重构', // 代码重构
'性能', // 性能优化
'测试', // 添加或修改测试代码
'构建', // 构建过程或工具变动
'配置', // 配置文件变动
'版本', // 版本号变更
'回滚', // 代码回滚
'其他' // 其他变更
]
],
'type-case': [0], // 类型大小写不作要求
'type-empty': [0], // 类型不能为空
'subject-max-length': [2, 'always', 100], // 主题最大长度为 100
'subject-case': [0], // 主题大小写不作要求
'subject-empty': [2, 'never'], // 主题不能为空
'body-max-line-length': [2, 'always', 100], // 详细描述每行最大长度为 100
'footer-max-line-length': [2, 'always', 100] // 关联问题每行最大长度为 100
}
};
使用husky生成commit-msg文件,验证提交信息
shell
npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
新的问题每次都让开发在提交git 时候按照标准规范提交代码实际是一件麻烦的事,我们可以使用一个工具:Commitizen,这里直接推荐使用 czg
shell
npm install -D czg
在文件 .commitlintrc.js
js
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const scopes = fs
.readdirSync(path.resolve(__dirname, 'src'), { withFileTypes: true })
.filter((dirent) => dirent.isDirectory())
.map((dirent) => dirent.name.replace(/s$/, ''));
// precomputed scope
const scopeComplete = execSync('git status --porcelain || true')
.toString()
.trim()
.split('\n')
.find((r) => ~r.indexOf('M src'))
?.replace(/(\/)/g, '%%')
?.match(/src%%((\w|-)*)/)?.[1]
?.replace(/s$/, '');
/** @type {import('cz-git').UserConfig} */
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'],
'subject-case': [0],
'type-enum': [
2,
'always',
[
'feat',
'fix',
'perf',
'style',
'docs',
'test',
'refactor',
'build',
'ci',
'chore',
'revert',
'wip',
'workflow',
'types',
'release',
],
],
},
prompt: {
/** @use `yarn commit :f` */
alias: {
f: 'docs: fix typos',
r: 'docs: update README',
s: 'style: update code format',
b: 'build: bump dependencies',
c: 'chore: update config',
},
customScopesAlign: !scopeComplete ? 'top' : 'bottom',
defaultScope: scopeComplete,
scopes: [...scopes, 'mock'],
allowEmptyIssuePrefixs: false,
allowCustomIssuePrefixs: false,
// English
typesAppend: [
{ value: 'wip', name: 'wip: work in process' },
{ value: 'workflow', name: 'workflow: workflow improvements' },
{ value: 'types', name: 'types: type definition file changes' },
],
// 中英文对照版
// messages: {
// type: '选择你要提交的类型 :',
// scope: '选择一个提交范围 (可选):',
// customScope: '请输入自定义的提交范围 :',
// subject: '填写简短精炼的变更描述 :\n',
// body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n',
// breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n',
// footerPrefixsSelect: '选择关联issue前缀 (可选):',
// customFooterPrefixs: '输入自定义issue前缀 :',
// footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
// confirmCommit: '是否提交或修改commit ?',
// },
// types: [
// { value: 'feat', name: 'feat: 新增功能' },
// { value: 'fix', name: 'fix: 修复缺陷' },
// { value: 'docs', name: 'docs: 文档变更' },
// { value: 'style', name: 'style: 代码格式' },
// { value: 'refactor', name: 'refactor: 代码重构' },
// { value: 'perf', name: 'perf: 性能优化' },
// { value: 'test', name: 'test: 添加疏漏测试或已有测试改动' },
// { value: 'build', name: 'build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)' },
// { value: 'ci', name: 'ci: 修改 CI 配置、脚本' },
// { value: 'revert', name: 'revert: 回滚 commit' },
// { value: 'chore', name: 'chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)' },
// { value: 'wip', name: 'wip: 正在开发中' },
// { value: 'workflow', name: 'workflow: 工作流程改进' },
// { value: 'types', name: 'types: 类型定义文件修改' },
// ],
// emptyScopesAlias: 'empty: 不填写',
// customScopesAlias: 'custom: 自定义',
},
};
package.json 配置
js
"scripts": {
"commit": "czg"
}
排除校验文件
.prettierignore
bash
/dist/*
/html/*
.local
/node_modules/**
**/*.svg
**/*.sh
/public/*
.eslintignore
shell
*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
.local
/bin
Dockerfile
.stylelintignore
shell
/node_modules/*
/dist/*
/html/*
/public/*