# 项目集成与配置范式
本文为简化版,完整版请参阅 集成 Git Hooks,建议使用简化版本。关联版本可以进行知识了解和扩展。
commit 规范可以参考 GitCommit 规范
# 一、Git Hooks(git 钩子)
Git Hooks 传送门
# 客户端钩子
# Husky
Husky 是在提交或推送时,自动化 检查提交信息、检查代码 和 运行测试。
根据 Husky 快速开始指引进行安装与配置。通过 Husky 中 pre-commit 运行 lint-staged
# 0. 前提 项目中已经初始化过 git | |
git init | |
# 1. 安装 husky | |
pnpm add --save-dev husky | |
# 2. 初始化 .husky 中脚本,以及 package.json 中的命令 | |
pnpm exec husky init | |
# 3. 测试一下,提示 ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL Command "test" not found 说明成功了 | |
git commit -m "Keep calm and commit" |
# 1.2 lint-staged
提交代码前对暂存的 git 文件运行格式化程序和代码检查程序等任务,不要让 💩 溜进你的代码库!
保证项目格式与风格的一致性
可根据 lint-staged 的 readme.md 进行安装以及学习相关命令与配置。
# 安装 lint-staged
pnpm add --save-dev lint-staged |
# 安装 ESlint、Stylelint、Prettier, 并编辑相关配置。
若还有其他工具需要集成,请直接安装配置即可(主要是提交前需要处理的任务,需要在 lint-staged.config.mjs 中配置)。其中 lingt-stage 的 readme 中提到了一些工具可以尝试。
# ESlint 安装与配置
ESlint 传送门安装过程与配置参数
# ESlint 安装
pnpm create @eslint/config@latest eslint-config-prettier eslint-plugin-stylelint | |
# - eslint-config-prettier 处理 ESlint 与 prettier 格式化冲突的插件(需要手动配置) | |
# - eslint-plugin-stylelint 处理 ESlint 与 stylelint 内联样式格式化冲突的插件(需要手动配置) | |
# 以下是安装过程提示内容,完毕后会在项目中,生成 eslint.config.mjs 配置文件 | |
# 1. What do you want to lint? | |
# JavaScript(输入) | |
# 2. How would you like to use ESLint? | |
# To check syntax and find problems(输入) | |
# 3. What type of modules does your project use? | |
# JavaScript modules (import/export)(输入) | |
# 4. Which framework does your project use? | |
# Vue.js(输入) | |
# 5. Does your project use TypeScript? | |
# Yes / No(输入) | |
# 6. Where does your code run? | |
# Browser Node(输入) | |
# 7. Which language do you want your configuration file be written in? | |
# JavaScript(输入) | |
# 8. Would you like to install them now? | |
# Yes(输入) | |
# 9. Would you like to install them now? | |
# pnpm(输入) |
# ESlint 配置
# 基于 ESlint 自动创建文件进行调整 | |
import globals from "globals"; // 解决 no-undef 报错,ESLint 中不允许使用未定义的变量 | |
import tseslint from "typescript-eslint"; // 包含 @typescript-eslint/parse 与 @typescript-eslint/eslint-plugin | |
import pluginVue from "eslint-plugin-vue"; | |
import { defineConfig } from "eslint/config"; | |
# custome config | |
import vueParser from 'vue-eslint-parser'; //eslint 的 vue 解析器:专门用于识别 .vue 文件的模板、脚本和样式块 | |
import prettier from 'eslint-plugin-prettier'; //eslint 中使用 prettier 插件:将 Prettier 作为 ESLint 的规则运行 | |
import prettierConfig from 'eslint-config-prettier'; //eslint 使用 prettier 配置:关闭所有可能引起冲突的 | |
/** | |
* ESLint 核心配置结构说明: | |
* 1. ignores: [免检区] 排除不需要扫描的文件 | |
* 2. files: [应用区] 声明当前配置块对哪些文件生效 | |
* 3. languageOptions: [理解区] 设置解析器、全局变量、语法版本 | |
* 4. plugins: [工具区] 引入检查能力扩展包,但不代表开启任何规则 | |
* 5. extends: [批量启动] 插件预设的一组规则(在 Flat Config 中通常直接展开在 rules 中) | |
* 6. rules: [准则区] 开启 / 关闭具体的检查标准,可以直接设置级别,也可以引入插件预设的成套规则, | |
* 与 plugins 配合使用时,规则名需要加上插件前缀(如 'vue/no-unused-vars')以区分来源 | |
* | |
* 配置块的优先级: | |
* Flat Config 是级联的。后定义的配置块如果匹配到相同文件,会覆盖或合并之前的配置。 | |
* 1. ignores > 2. files > 3. languageOptions > 4. plugins > 5. extends > 6. rules | |
*/ | |
export default defineConfig([ | |
// 全局忽略:优先级最高,被匹配的文件将跳过所有逻辑 | |
// 注意:ignores 独立存在时是全局生效的 | |
{ | |
ignores: [ | |
'.husky/', | |
'.vscode/', | |
'node_modules/', | |
'dist/', | |
'public/', | |
'src/static/', | |
'src/uni_modules/', | |
'*.config.js', | |
], | |
}, | |
//--- 1. 基础共享配置 --- | |
// 目的:为所有支持的文件类型提供通用的运行环境 | |
{ | |
// 决定此块配置的 “作用域” | |
files: ['**/*.{js,mjs,cjs,ts,mts,cts,vue}'], | |
// 告诉 ESLint 如何 “读懂” 代码 | |
languageOptions: { | |
// 声明预定义的全局变量,防止报 “变量未定义” 错误 | |
globals: { | |
...globals.browser, | |
...globals.node, | |
// 定义一个名为 myCustomGlobal 的全局变量,readonly 不允许代码修改它,writable 可以修改 | |
// myCustomGlobal: "readonly" | |
}, | |
// 解析语法时的具体参数 | |
parserOptions: { | |
ecmaVersion: 'latest', // 识别最新的 ECMAScript 语法 | |
sourceType: 'module', // 识别 ES Modules (import/export) | |
ecmaFeatures: { jsx: false }, // 是否解析 JSX 语法 | |
}, | |
}, | |
}, | |
//--- 2. Vue 专属配置 --- | |
// 逻辑:先用 vue-eslint-parser 解析 SFC 外壳,再将其中的 <script> 交给 TS 解析器 | |
{ | |
files: ['**/*.vue'], | |
languageOptions: { | |
// 指定主解析器,vue-eslint-parser 负责拆分 template/script/style | |
parser: vueParser, | |
parserOptions: { | |
// 告诉 vue-eslint-parser 遇到 <script lang="ts"> 时用谁处理 | |
parser: tseslint.parser, | |
extraFileExtensions: ['.vue'], // 确保 TS 解析器能识别 .vue 内部的代码 | |
}, | |
}, | |
// 引入扩展插件包(提供新规则,但不代表开启) | |
plugins: { | |
vue: pluginVue, | |
'@typescript-eslint': tseslint.plugin, | |
prettier: prettier, | |
}, | |
// 真正的 “规则手册”,在这里开关各项检查标准 | |
rules: { | |
// 展开 Vue 推荐规则 | |
...pluginVue.configs['flat/recommended'].rules, | |
...tseslint.configs.recommended.rules | |
// [冲突处理] 必须放在规则列表后面,确保关闭所有与 Prettier 冲突的规则 | |
...prettierConfig.rules, | |
// [自定义规则] 键名是插件前缀 / 规则名,值是报错级别 | |
'vue/multi-word-component-names': 'off', //off: 关闭(允许单单词组件名,如 App.vue) | |
'vue/attribute-hyphenation': 'error', //error: 强制报错(Vue 模板属性强制使用连字符) | |
// [规则替代逻辑] 关闭原生规则,开启插件对应的增强规则以支持特殊语法 | |
'vue/no-unused-vars': ['error', { ignorePattern: '^_' }], // 扫描模版和 js 中内容 | |
'no-unused-vars': 'off', // 扫描 template 变量 | |
'@typescript-eslint/no-unused-vars': [ | |
'error', | |
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' }, | |
], // 扫描 & lt;script> | |
// 将 Prettier 的格式错误直接显示为 ESLint 下划线错误 | |
'prettier/prettier': 'error', | |
}, | |
}, | |
//--- 3. JavaScript 专属配置 --- | |
{ | |
files: ['**/*.{js, mjs, cjs}'], | |
plugins: { | |
prettier: prettier, | |
}, | |
// Flat Config 中 recommended 规则的注入方式 | |
rules: { | |
'no-debugger': 'error', | |
'no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], | |
...prettierConfig.rules, | |
'prettier/prettier': 'error', | |
// 'eol-last': ['error', 'always'], // 强制文件末尾保留一行空行 | |
}, | |
}, | |
//--- 4. TypeScript 专属配置 --- | |
{ | |
files: ['**/*.{ts, mts, cts}'], | |
languageOptions: { | |
// 直接使用 TS 解析器解析纯 TS 文件,不涉及 Vue 的 AST 转换 | |
parser: tseslint.parser, | |
parserOptions: { | |
// 关联 tsconfig 使 ESLint 具备类型检查能力(如检查不合规的赋值) | |
project: './tsconfig.json', | |
}, | |
}, | |
plugins: { | |
'@typescript-eslint': tseslint.plugin, | |
prettier: prettier, | |
}, | |
rules: { | |
// 注入 TypeScript 官方推荐的校验逻辑 | |
// ...tseslint.configs.recommended[0].rules, | |
...tseslint.configs.recommended.rules, | |
...prettierConfig.rules, | |
'no-debugger': 'error', | |
'no-unused-vars': 'off', // 禁用原生规则,统一由 TS 规则处理 | |
'@typescript-eslint/no-unused-vars': [ | |
'error', | |
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' }, | |
], | |
'@typescript-eslint/no-explicit-any': 'off', // 允许使用 any 类型,提高开发灵活性 | |
'prettier/prettier': 'error', | |
// 'eol-last': ['error', 'always'], 结尾空行 | |
}, | |
}, | |
]); |
# ESlint 忽略文件配置
# Stylelint 安装与配置
styllint 传送门 安装过程与配置参数
# Stylelint 安装
pnpm create stylelint stylelint-config-prettier | |
# - stylelint-config-prettier 处理 stylint 与 prettier 格式化冲突 | |
# 以下是安装过程提示内容,完毕后会在项目中,生成 stylelint.config.mjs 配置文件 | |
# Then add the related dependencies using: | |
# pnpm add -D stylelint stylelint-config-standard | |
# Yes (输入) | |
# - stylelint-config-standard-scss 是对 scss 检查的依赖 | |
# - stylelint-config-standard 是对 css 检查的依赖 |
# Stylelint 配置
# 基于 Stylelint 自动创建文件进行调整 | |
/** @type {import("stylelint").Config} */ | |
export default { | |
defaultSeverity: 'error', // 所有规则默认报红 | |
// 继承官方推荐配置、Vue 适配配置和属性排序配置 | |
extends: [ | |
'stylelint-config-standard', // 标准 CSS 规则 | |
'stylelint-config-prettier', // 处理 stylelint 与 prettier 的冲突 | |
'stylelint-config-standard-scss', // 如果你使用 SCSS,请加上这个 | |
'stylelint-config-recommended-vue', // 核心:解析 Vue 文件中的 <style> | |
'stylelint-config-recess-order', // 核心:属性自动排序(位置、大小、字体等) | |
], | |
rules: { | |
// 自定义规则 | |
'no-empty-source': null, // 允许空的 style 标签(适配 Vue 模板开发阶段) | |
'unit-no-unknown': [true, { ignoreUnits: ['rpx'] }], // 适配 uni-app 的 rpx 单位 | |
'selector-class-pattern': null, // 关闭类名命名规范检查(允许驼峰或下划线) | |
'at-rule-no-unknown': [ | |
true, | |
{ | |
ignoreAtRules: ['mixin', 'include', 'extend', 'forward', 'use', 'tailwind'], | |
}, | |
], | |
// 允许 Vue 的深度选择器 :deep (), 对以下伪类放行。 | |
'selector-pseudo-class-no-unknown': [ | |
true, | |
{ | |
ignorePseudoClasses: ['deep', 'global', 'slotted', 'v-deep'], | |
}, | |
], | |
// 允许的深度选择器 ::v-deep, 对一下伪类放行 | |
'selector-pseudo-element-no-unknown': [ | |
true, | |
{ | |
// 允许 Vue 特有的伪元素 | |
ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'], | |
}, | |
], | |
// 关闭严格的值检查(防止 rpx 报错) | |
'declaration-property-value-no-unknown': null, | |
}, | |
overrides: [ | |
{ | |
files: ['**/*.{vue, scss}'], | |
customSyntax: 'postcss-html', // 必须有这个来处理 Vue 里的 <style> | |
}, | |
], | |
// 忽略的文件列表,建议与 .prettierignore 保持同步 | |
// ignoreFiles: [ | |
// 'node_modules/**/*', | |
// 'dist/**/*', | |
// 'public/**/*', | |
// 'src/uni_modules/**/*', | |
// '**/*.ts', | |
// '**/*.js', | |
// ], | |
}; |
# Stylelint 忽略文件配置
node_modules/ | |
dist/ | |
public/ | |
src/uni_modules/ | |
# 排除所有逻辑代码文件 | |
*.ts | |
*.js | |
*.tsx | |
*.jsx | |
*.json |
# Prettier 安装与配置
Prettier 传送门安装过程与配置参数
# Prettier 安装
pnpm add --save-dev --save-exact prettier |
# Prettier 配置
export default { | |
printWidth: 100, // 每行代码最大长度 | |
tabWidth: 2, // 缩进空格数 | |
useTabs: false, // 禁用 tab 缩进,用空格 | |
semi: true, // 语句末尾加分号 | |
singleQuote: true, // 用单引号 | |
vueIndentScriptAndStyle: true, // Vue 文件 script/style 是否缩进 | |
bracketSpacing: true, // 对象字面量括号间加空格({a: 1}) | |
trailingComma: 'es5', // 对象或数组最后一个元素后是否加尾逗号(ES5 规范) | |
arrowParens: 'always', // 箭头函数单个参数省略括号 always 总写,avoid 不写 | |
endOfLine: 'lf', // 换行符(LF,兼容 Linux/Mac) | |
htmlWhitespaceSensitivity: 'ignore', // HTML 空格不敏感(避免 Vue 模板换行报错) | |
jsxBracketSameLine: false, // JSX/TSX 中把 > 单独放一行(true 则和最后一个属性同行) | |
jsxSingleQuote: false, // JSX/TSX 中使用双引号(true 则用单引号) | |
}; |
# Prettier 忽略文件配置
# 继承ESLint忽略规则(可选) | |
.eslintignore | |
.stylelintignore | |
.prettierignore | |
# 额外忽略 | |
node_modules/ | |
dist/ | |
public/ | |
/src/uni_modules/* | |
.local | |
.output.js | |
*.md | |
*.sh | |
*.svg |
# package.json 配置
配置 lint:lint-staged 命令, 以运行代码检查器和代码格式化或其他任务 (代码检查与格式化)。
{ | |
"scripts":{ | |
"prepare": "husky", # husky init时,自动生成 | |
"lint:lint-staged": "lint-staged", # 手动添加,调用下方 lint-staged | |
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore" # 手动添加, 对相关后缀文件进行代码检查修复,同时忽略检查 .gittignore (可以不写) | |
}, | |
// 以下配置可以单独拆分到 lint-staged.config.mjs, 优先此种方式,单独配置暂未尝试。 | |
"lint-staged": { | |
"*.{js,ts,vue}": [ | |
"eslint --fix", | |
"stylelint --fix", | |
"prettier --write" | |
], | |
"*.{mjs,cjs,mts,cts,json}": [ | |
"prettier --write" | |
], | |
"*.{scss,css}": [ | |
"stylelint --fix", | |
"prettier --write" | |
], | |
"*.md": [ | |
"prettier --write" | |
] | |
}, | |
} |
export default { | |
"*.{js,ts,vue}": [ | |
"eslint --fix", | |
"stylelint --fix", | |
"prettier --write" | |
], | |
"*.{mjs,cjs,mts,cts,json}": [ | |
"prettier --write" | |
], | |
"*.{scss,css}": [ | |
"stylelint --fix", | |
"prettier --write" | |
], | |
"*.md": [ | |
"prettier --write" | |
] | |
} |
# 更新 pre-commit 命令
echo "pnpm run lint:lint-staged" > .husky/pre-commit |
# 1.3 commitlint
验证 git commit message 是否符合规范
commitlint 传送门 安装与配置
# commitlint 安装
pnpm add -D @commitlint/cli @commitlint/config-conventional |
# commitlint 配置
echo "export default { extends: ['@commitlint/config-conventional'] };" > commitlint.config.mjs |
export default { | |
extends: ['@commitlint/config-conventional'], | |
rules: { | |
'subject-case': [0], //subject 大小写不做校验 | |
'type-enum': [ | |
2, | |
'always', | |
[ | |
'feat', // 新增功能 | |
'fix', // 修复缺陷 | |
'docs', // 文档变更 | |
'style', // 代码格式(不影响功能,例如空格、分号等格式修正) | |
'refactor', // 代码重构(不包括 bug 修复、功能新增) | |
'perf', // 性能优化 | |
'test', // 添加疏漏测试或已有测试改动 | |
'build', // 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等) | |
'ci', // 修改 CI 配置、脚本 | |
'revert', // 回滚 commit | |
'chore', // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例) | |
], | |
], | |
}, | |
}; |
# husky 添加命令
:::
警告
Windows 用户请注意:请确保所有 **husky** 文件 **UTF-8** 均已编码。如果使用其他格式,运行时可能会出现错误,例如 “无法执行二进制文件”。
同时,确保 **git** 和 **husky** 初始化完毕。
:::
echo "pnpm exec commitlint --edit \${1}" > .husky/commit-msg |
:::
至此,客户端钩子配置基本完毕。可以 commit 验证功能了。若是有问题就处理问题即可。
:::
# 服务端钩子
通常在 CI/CD 中使用较为常见, 目前暂无使用经验。