前言
前端工程化, 是前端开发中一个重要的话题, 它涉及到开发流程/代码规范/自动化构建/单元测试/持续集成等.
其中, git
提交规范是前端工程化的一个重要组成部分, 它有助于团队成员之间的协作/代码的版本控制/代码的审计等.
通常会使用一些工具来规范git提交规范, 如husky
/lint-staged
/commitlint
等.
以上是AI的回答, 本文的目的只是因为eslint9+
之后, 配置格式发生了一些修改, 所以用来记录以备后续使用.
项目搭建
创建基本内容
这里使用pnpm
作为包管理工具. 但是整个过程和npm
/yarn
/bun
/pnpm
等工具无关, 可以根据需要选择合适的工具.
创建一个项目的package.json
和.git
文件:
bash
pnpm init git init
移除package.json
的main
字段后如下:
package.json
json
{
"name": "example-1",
"version": "1.0.0",
"description": "",
"scripts": {},
"keywords": [],
"author": "",
"license": "ISC"
}
main
字段是指在引入时的默认入口文件, 我们现在不需要使用main
字段, 所以将其移除.
安装依赖
bash
pnpm add -D husky lint-staged commitlint @commitlint/config-conventional @commitlint/cli pnpm add -D eslint prettier @eslint/js @types/eslint__js typescript typescript-eslint
husky
是git
钩子工具, 用于在git
提交前执行一些命令.lint-staged
是用于在git
提交前执行一些命令.commitlint
是用于校验git
提交规范.@commitlint/cli
是commitlint
的命令行工具, 用于校验git
提交规范.@commitlint/config-conventional
是commitlint
的配置文件, 用于校验git
提交规范.eslint
是lint
工具, 用于校验代码规范.prettier
是lint
工具, 用于格式化代码.@eslint/js
是eslint
的配置文件, 用于校验代码规范.typescript
是ts
编译器, 用于编译ts
代码.typescript-eslint
是eslint
的插件, 用于校验ts
代码规范.
配置husky
执行一下命令, 将husky
的安装配置到package.json
中:
bash
pnpm exec husky init
执行完成后, 项目目录下会新增一个.husky
文件夹,
同时package.json
的scripts
会多出一个prepare
字段, 这是npm
的执行hook
.
package.json
json
{
"name": "example-1",
"version": "1.0.0",
"description": "",
"scripts": {
"prepare": "husky"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@commitlint/config-conventional": "^19.2.2",
"@eslint/js": "^9.9.0",
"@types/eslint__js": "^8.42.3",
"commitlint": "^19.4.0",
"eslint": "^9.9.0",
"husky": "^9.1.4",
"lint-staged": "^15.2.9",
"prettier": "^3.3.3",
"typescript": "^5.5.4",
"typescript-eslint": "^8.1.0"
}
}
可能会用到的一些 npm-hooks:
preinstall
: 在npm install
之前执行postinstall
: 在npm install
完成后立即执行prepare
: 在npm publish
npm pack
之前执行, 或者不携带参数的npm install
时运行preuninstall
: 在npm uninstall
命令前执行postuninstall
: 在npm uninstall
命令后执行
这里husky
是在prepare
添加的, 所以在npm install
时, 会执行husky
的安装配置.
然后再在package.json
中添加以下内容:
package.json
json
{
"name": "example-1",
"version": "1.0.0",
"description": "",
"scripts": {
"prepare": "husky"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@commitlint/config-conventional": "^19.2.2",
"@eslint/js": "^9.9.0",
"@types/eslint__js": "^8.42.3",
"commitlint": "^19.4.0",
"eslint": "^9.9.0",
"husky": "^9.1.4",
"lint-staged": "^15.2.9",
"prettier": "^3.3.3",
"typescript": "^5.5.4",
"typescript-eslint": "^8.1.0"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{ts,tsx,js}": [
"eslint"
],
"*.{ts,tsx,js,json,html,yml,css,less,scss,md}": [
"prettier --write"
]
}
}
其中, husky
字段中的hooks
字段是指git
操作时的hook
.
lint-staged
字段配置校验代码的方式
详细配置: lint-staged
常用的git hook
:
pre-commit
: 在git commit
之前执行commit-msg
: 在git commit
时执行post-commit
: 在git commit
后执行pre-push
: 在git push
之前执行post-push
: 在git push
后执行pre-rebase
: 在git rebase
之前执行post-rebase
: 在git rebase
后执行
然后修改.husky/pre-commit
文件的内容为:
pnpm lint-staged
在git
提交前执行lint-staged
, lint-staged
会根据package.json
的配置执行eslint
和prettier
的校验.
然后配置对应的 eslint
和prettier
.
typescript配置
如果不需要ts
可以忽略本段.
bash
pnpm tsc --init
执行以上命令, 会创建一个tsconfig.json
文件.
tsconfig.json
json
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Projects */
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
解开baseUrl
的注释, 并且修改lib
为:
json
{ "lib": [ "ESNext", "DOM" ] }
再加上includes
和excludes
, 移除注释的内容:
tsconfig.json
json
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
"target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"lib": ["ESNext", "DOM"],
/* Modules */
"module": "commonjs" /* Specify what module code is generated. */,
// "rootDir": "./", /* Specify the root folder within your source files. */
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
"baseUrl": "./" /* Specify the base directory to resolve non-relative module names. */,
/* ... */
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
"skipLibCheck": true /* Skip type checking all .d.ts files. */
},
"exclude": ["node_modules"],
"include": ["src/**/*"]
}
配置eslint
创建eslint.config.mjs
文件, 并添加以下内容:
eslint.config.mjs
javascript
import eslint from '@eslint/js';
import globals from 'globals';
import tseslint from 'typescript-eslint';
export default tseslint.config(eslint.configs.recommended, ...tseslint.configs.recommended, {
languageOptions: {
globals: { ...globals.node, ...globals.es5 },
},
});
如果不需要ts
:
eslint.config.mjs
javascript
import eslint from '@eslint/js';
import globals from 'globals';
export default [
eslint.configs.recommended,
{
languageOptions: {
globals: { ...globals.node, ...globals.es2025 },
},
},
];
这里因为eslint
默认没有浏览器API或者NodejsApi, 所以需要安装globals包, 并展开在这里.
至于需要展开哪些, 就按需配置了.
并且改变package.json
的type
字段为module
.
package.json
json
{
"name": "example-1",
"version": "1.0.0",
"description": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"prepare": "husky"
},
"type": "module",
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@commitlint/config-conventional": "^19.2.2",
"@eslint/js": "^9.9.0",
"@types/eslint__js": "^8.42.3",
"commitlint": "^19.4.0",
"eslint": "^9.9.0",
"husky": "^9.1.4",
"lint-staged": "^15.2.9",
"prettier": "^3.3.3",
"typescript": "^5.5.4",
"typescript-eslint": "^8.1.0"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{ts,tsx,js}": [
"eslint"
],
"*.{ts,tsx,js,json,html,yml,css,less,scss,md}": [
"prettier --write"
]
}
}
这样eslint
就配置完成了, 新建一个文件测试一下.
app.js
javascript
var a = 1;
console.log(1)
运行命令:
bash
pnpm eslint
正确的提示了错误信息:
如果需要自定义rule
, 可以添加新的规则, 比如不对未使用的变量报错, 而是输出警告:
eslint.config.mjs
javascript
import eslint from '@eslint/js';
import globals from 'globals';
import tseslint from 'typescript-eslint';
export default tseslint.config(eslint.configs.recommended, ...tseslint.configs.recommended, {
languageOptions: {
globals: { ...globals.node, ...globals.es5 },
},
rules: {
'no-unused-vars': 'warn',
'@typescript-eslint/no-unused-vars': 'warn',
},
});
执行eslint
命令, 会输出警告:
配置prettier
prettier
是用来格式化代码的, 在vscode
上可以按照prettier
的插件, 在settings.json
中配置editor.formatOnSave
为true
, 这样在保存时, 会自动格式化代码.
同时设置默认格式化方式为prettier
插件:
vscode-settings.json
json
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": "always",
"source.organizeImports": "always"
},
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
然后新建.pretterrc
文件用来配置prettier
规则:
{
"singleQuote": true,
"endOfLine": "lf",
"trailingComma": "all",
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"bracketSpacing": true,
"jsxSingleQuote": true
}
其中的内容根据需求自行配置: prettier-options
prettier
可能会和eslint
有冲突, 所以需要再配置一下eslint
的规则.
安装eslint-config-prettier
和eslint-plugin-prettier
:
bash
pnpm add -D eslint-config-prettier eslint-plugin-prettier
修改eslint.config.mjs
文件:
eslint.config.mjs
javascript
import eslint from '@eslint/js';
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
import globals from 'globals';
import tseslint from 'typescript-eslint';
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
eslintPluginPrettierRecommended,
{
languageOptions: {
globals: { ...globals.node, ...globals.es5 },
},
rules: {
'no-unused-vars': 'warn',
'@typescript-eslint/no-unused-vars': 'warn',
},
},
);
配置完成后, 执行eslint
命令, 会提示错误:
如果有需要忽略的文件, 可以在项目中添加.prettierignore
文件: prettier-ignore
配置commitlint
新建commitlint.config.mjs
文件, 并添加以下内容:
commitlint.config.mjs
javascript
export default {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
['build', 'chore', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test'],
],
},
};
所有的
rules
: commitlint-rulesrules
的每一个值对应:
- 警告等级: 0: 关闭, 1: 警告, 2: 错误
- 适用:
always
: 始终,never
: 禁止 rule
的值
在.husky
文件夹新增commit-msg
文件:
pnpm commitlint --edit $1
然后测试一下.
初始化git
:
bash
git init
添加文件到暂存区:
bash
git add src/test.js
test.js
的内容:
test.js
javascript
var a = 1
提交:
bash
git commit -m "test"
提示错误:
可以看到, 根据lint-staged
的配置, 使用了eslint
对文件进行了校验, 同时因为使用了var
声明变量, 所以eslint
报错了.
修改内容:
test.js
javascript
const a = 1;
再次提交:
bash
git add src/test.js git commit -m "test"
这次是commitlint
报错:
- 提交的内容是空的
- 提交的类型是空的
我们修改一下提交信息:
bash
git commit -m "feat: test"
可以看到成功提交了.
但是这样提交会有点麻烦, 毕竟一个字打错了就得重来, 所以可以使用更方便得可视化提交工具: commitizen
commitizen
安装commitizen
及相关依赖:
bash
pnpm add -D @commitlint/cz-commitlint commitizen inquirer@9
@commitlint/cz-commitlint
是commitlint
的commitizen
插件, 用来结合commitlint
和commitizen
.
配置package.json
:
package.json
json
{
"name": "example-1",
"version": "1.0.0",
"description": "",
"scripts": {
"commit": "git-cz",
"prepare": "husky"
},
"type": "module",
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@commitlint/cli": "^19.4.0",
"@commitlint/config-conventional": "^19.2.2",
"@commitlint/cz-commitlint": "^19.4.0",
"@eslint/js": "^9.9.0",
"@types/eslint__js": "^8.42.3",
"commitizen": "^4.3.0",
"commitlint": "^19.4.0",
"eslint": "^9.9.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"globals": "^15.9.0",
"husky": "^9.1.4",
"inquirer": "9",
"lint-staged": "^15.2.9",
"prettier": "^3.3.3",
"typescript": "^5.5.4",
"typescript-eslint": "^8.1.0"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{ts,tsx,js}": [
"eslint"
],
"*.{ts,tsx,js,json,html,yml,css,less,scss,md}": [
"prettier --write"
]
},
"config": {
"commitizen": {
"path": "@commitlint/cz-commitlint"
}
}
}
执行命令:
bash
pnpm commit
可以看到, 能够通过命令行进行操作提交信息. 但是这里目前是英语, 我们可以配置commitlint
来支持中文:
commitlint.config.mjs
javascript
export default {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
['build', 'chore', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test'],
],
},
prompt: {
settings: {},
messages: {
skip: ':skip',
max: 'upper %d chars',
min: '%d chars at least',
emptyWarning: 'can not be empty',
upperLimitWarning: 'over limit',
lowerLimitWarning: 'below limit'
},
questions: {
type: {
description: "Select the type of change that you're committing:",
enum: {
feat: {
description: '新增功能',
title: 'Features',
emoji: '✨',
},
fix: {
description: '修复bug',
title: 'Bug Fixes',
emoji: '🐛',
},
docs: {
description: '文档',
title: 'Documentation',
emoji: '📚',
},
style: {
description: '不影响逻辑得代码格式',
title: 'Styles',
emoji: '💎',
},
refactor: {
description: '没有新功能或者修改',
title: 'Code Refactoring',
emoji: '📦',
},
perf: {
description: '代码优化',
title: 'Performance Improvements',
emoji: '🚀',
},
test: {
description: '添加或修改测试',
title: 'Tests',
emoji: '🚨',
},
build: {
description: '影响构建得更改',
title: 'Builds',
emoji: '🛠',
},
ci: {
description: '更改脚手架或脚本',
title: 'Continuous Integrations',
emoji: '⚙️',
},
chore: {
description: "其他不修改src和test文件的更改",
title: 'Chores',
emoji: '♻️',
},
revert: {
description: '恢复的commit',
title: 'Reverts',
emoji: '🗑',
},
},
},
subject: {
description: 'Write a short, imperative tense description of the change',
},
body: {
description: 'Provide a longer description of the change',
},
},
}
};
详细配置: prompt
再次执行命令:
bash
pnpm commit
可以看到提交说明成了中文的.
结语
在本文中, 我们详细探讨了如何在前端项目中实施Git提交规范, 并利用一系列工具如husky/lint-staged以及commitlint来确保每次提交都符合既定的标准.这些工具不仅提升了代码质量, 还加强了团队间的协作效率.
通过上述步骤, 我们已经成功地设置了一个能够自动检查代码风格/格式化代码并验证提交消息的环境.这不仅减少了人工审查的工作量, 还确保了每次提交都是高质量的, 从而提高了项目的整体稳定性和可维护性.
最后, 我们还引入了commitizen来简化提交过程, 使得编写符合规范的提交消息变得更加直观和便捷.无论是对于新手还是经验丰富的开发者来说, 这都是一个非常实用的功能.
随着项目的不断演进和技术栈的变化, 这些配置可能也需要随之调整.
书写本文时的环境:
- nodejs > 18.x
- pnpm > 8.x
依赖及其版本:
package.json
json
{
"name": "example-1",
"version": "1.0.0",
"description": "",
"scripts": {
"commit": "git-cz",
"prepare": "husky"
},
"type": "module",
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@commitlint/cli": "^19.4.0",
"@commitlint/config-conventional": "^19.2.2",
"@commitlint/cz-commitlint": "^19.4.0",
"@eslint/js": "^9.9.0",
"@types/eslint__js": "^8.42.3",
"commitizen": "^4.3.0",
"commitlint": "^19.4.0",
"eslint": "^9.9.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"globals": "^15.9.0",
"husky": "^9.1.4",
"inquirer": "9",
"lint-staged": "^15.2.9",
"prettier": "^3.3.3",
"typescript": "^5.5.4",
"typescript-eslint": "^8.1.0"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{ts,tsx,js}": [
"eslint"
],
"*.{ts,tsx,js,json,html,yml,css,less,scss,md}": [
"prettier --write"
]
},
"config": {
"commitizen": {
"path": "@commitlint/cz-commitlint"
}
}
}