项目搭建规范的配置
# 项目搭建规范
在一个项目中,写作开发的代码风格和规范至关重要,如何保证一个i项目的风格呢?
通过规范文档定义,开发人员在开发前熟悉规范显然不是很合理,无论对项目代码风格多么的熟悉,人总会出错,比如忘记加分号、单引号和双引号混用、单行代码过长、缩进错误等等。
通过一些列辅助工具,将项目的风格规范交给机器处理,才是正解。各大开源项目中都有来规范代码风格的工具。
本文通过在VSCode中搭建一个Vue项目,配置相关工具以及代码库依赖来演示项目搭建规范。
准备工作,初始化一个Vue3的项目:
npm init vue@latest
注意:
- 创建项目时,问题 Add ESLint for code quality? ... No / Yes 选择了Yes,让脚手架自动帮安装Vue中ESLint的相关依赖。
- Add Prettier for code formatting? ... No / Yes 随意选择,之后会再手动安装做演示。
# 集成editorconfig
EditorConfig (opens new window) 有助于为不同 IDE 编辑器上处理同一项目的多个开发人员维护一致的编码风格。有很多项目 (opens new window)都在使用这个工具,比如在React (opens new window)以及Vue2 (opens new window)的项目中,都可以见到它的配置文件。
在VSCode中需要安装插件EditorConfig for VS Code (opens new window) 。VSCode在安装插件会默认读取项目中根目录下的.editorconfig
以规范我们的代码。
在项目根目录中创建配置文件.editorconfig
:
# http://editorconfig.org
root = true
[*] # 表示所有文件适用
charset = utf-8 # 设置文件字符集为 utf-8
indent_style = space # 缩进风格(tab | space)
indent_size = 2 # 缩进大小
end_of_line = lf # 控制换行类型(lf | cr | crlf)
trim_trailing_whitespace = true # 去除行首的任意空白字符
insert_final_newline = true # 始终在文件末尾插入一个新行
max_line_length = 80 # 单行最大字符
[*.md] # 表示仅 md 文件适用以下规则
max_line_length = off # off 表示关闭
trim_trailing_whitespace = false
上面的中括号中是通配符,表示要匹配哪种文件应用代码规范,详见官网File Format Details (opens new window)章节。
接着下面定义匹配到的文件的规范属性,所有的配置属性可见属性列表 (opens new window)。
# 配置prettier
Prettier (opens new window) 是一款强大的代码格式化工具,支持 JavaScript、TypeScript、CSS、SCSS、Less、JSX、Angular、Vue、GraphQL、JSON、Markdown 等语言,基本上前端能用到的文件格式它都可以搞定,是当下最流行的代码格式化工具。
在VSCode中可安装插件Prettier - Code formatter (opens new window),然后在用户的settings.json
中添加一行配置,将Prettier设置为全局默认格式化工具。
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
}
VSCode会按照以下优先级来读取配置:
- 读取项目中根目录下的Prettier配置文件 (opens new window),如
.prettierrc
,.prettierrc.js
- 读取
.editorconfig
- VSCode中的Prettier配置。只要找到就忽略VSCode集成插件的配置。
在项目根目录下创建.prettierrc
:
{
"useTabs": false,
"tabWidth": 2,
"printWidth": 80,
"singleQuote": true,
"trailingComma": "none",
"semi": false,
"arrowParens": "avoid"
}
配置详见官方文档Options (opens new window),上面的配置含义如下:
useTabs:使用tab缩进还是空格缩进,选择false;
tabWidth:tab是空格的情况下,是几个空格,选择2个;
printWidth:当行字符的长度,推荐80,也有人喜欢100或者120;
singleQuote:使用单引号还是双引号,选择true,使用单引号;
trailingComma:在多行输入的尾逗号是否添加,设置为
none
;semi:语句末尾是否要加分号,默认值true,选择false表示不加;
arrowParens:是否保留箭头函数的括号,
always
总保留,avoid
尽可能移除
我们也可以创建Prettier的忽略文件,来忽略Preitter对部分文件做格式化处理。
创建.prettierignore
忽略文件
/dist/*
.local
.output.js
/node_modules/**
**/*.svg
**/*.sh
/public/*
此忽略文件是在.gitignore
上的补充,如果没有要补充的,可以不要这个文件,Prettier会使用.gitignore
。
在项目中安装prettier依赖,可以直接运行脚本来格式化代码:
npm install prettier -D
配置脚本(只是为了演示,开发中无需配置)
"scripts": {
"prettier": "prettier --write ."
},
有如下代码:
<script setup lang="ts">
import WelcomeItem from './WelcomeItem.vue';
import DocumentationIcon from './icons/IconDocumentation.vue';
import ToolingIcon from './icons/IconTooling.vue';
import EcosystemIcon from './icons/IconEcosystem.vue';
import CommunityIcon from './icons/IconCommunity.vue';
import SupportIcon from "./icons/IconSupport.vue"
</script>
执行npm run prettier
后,代码会按照定义规范自动格式化:
<script setup lang="ts">
import WelcomeItem from './WelcomeItem.vue'
import DocumentationIcon from './icons/IconDocumentation.vue'
import ToolingIcon from './icons/IconTooling.vue'
import EcosystemIcon from './icons/IconEcosystem.vue'
import CommunityIcon from './icons/IconCommunity.vue'
import SupportIcon from './icons/IconSupport.vue'
</script>
不过我们通常不会手动去执行格式化代码,而是通过ESLint进行代码检查和格式化。
# 配置ESLint
在创建项目时,脚手架已自动为我们生成了ESLint的配置.eslintrc.cjs
:
/* eslint-env node */
require("@rushstack/eslint-patch/modern-module-resolution");
module.exports = {
"root": true,
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended",
"@vue/eslint-config-typescript/recommended",
"@vue/eslint-config-prettier"
]
}
如果在创建项目时,没有自动安装Prettier,可手动安装相关依赖:
npm i -D prettier @vue/eslint-config-prettier
然后在extends
中添加"@vue/eslint-config-prettier"
依赖即可。
在VSCode中安装插件ESLint (opens new window),默认会读取我们项目中的.eslintrc.cjs
配置来检查我们的代码规范。
# 配置Husky
虽然我们已经要求项目使用eslint了,但是不能保证组员提交代码之前都将eslint中的问题解决掉了:
也就是我们希望保证代码仓库中的代码都是符合eslint规范的;
那么我们需要在组员执行
git commit
命令的时候对其进行校验,如果不符合eslint规范,那么自动通过规范进行修复;
Husky (opens new window)是一个git hook工具,可以帮助我们触发git提交的各个阶段:pre-commit、commit-msg、pre-push。
那么我们可以使用Husky在做校验。
自动安装:
npx husky-init && npm install # npm
npx husky-init && yarn # Yarn 1
yarn dlx husky-init --yarn2 && yarn # Yarn 2+
pnpm dlx husky-init && pnpm install # pnpm
上面的命令会初始化Husky配置:
- 修改
package.json
文件,添加Scripts脚本"prepare": "husky install"
- 并创建
.husky
目录,新建一个pre-commit
示例,这个示例默认运行npm run test
在pre-commit
添加npm run lint
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint
当使用git commit
提交代码前,Husky会自动触发Git pre-commit的Hook,执行eslint来校验代码是否符合ESLint规范,并修复不规范的代码,下面是执行示例:
git commit -m "commit test"
> test2@0.0.0 lint
> eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore
create mode 100644 src/components/icons/IconSupport.vue
create mode 100644 src/components/icons/IconTooling.vue
create mode 100644 src/main.ts
create mode 100644 src/router/index.ts
create mode 100644 src/stores/counter.ts
create mode 100644 src/views/AboutView.vue
create mode 100644 src/views/HomeView.vue
create mode 100644 tsconfig.app.json
create mode 100644 tsconfig.config.json
create mode 100644 tsconfig.json
create mode 100644 tsconfig.vitest.json
create mode 100644 vite.config.ts
使用husky add .
,可以创建Hook:
npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
.husky/commit-msg
指定要创建哪一个阶段的GitHook- 引号中的内容
"npx --no-install commitlint --edit $1"
表示要创建的脚本内容
上面的命令创建出的脚本如下:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx --no-install commitlint --edit
# 配置Commit规范
通常我们的git commit会按照统一的风格来提交,这样可以快速定位每次提交的内容,方便之后对版本进行控制。
规范的Commit message 都包括三个部分:Header,Body 和 Footer。
<type>(<scope>): <subject>
// 空一行
<body>
// 空一行
<footer>
Header 部分是必需的,且只有一行,包括三个字段:type
(必需)、scope
(可选)和subject
(必需)。
Body 和 Footer 可以省略。Body 部分是对本次 commit 的详细描述,可以分成多行。
Footer 部分是对不兼容变动和关联的issue进行描述。
不管是哪一个部分,任何一行都不得超过72个字符(或100个字符)。这是为了避免自动换行影响美观。
关于Commit的提交规范的详细介绍,可参考Commit message 和 Change log 编写指南 (opens new window)。
也可以看下Vue的Commit Messgae (opens new window),以及Vue对Commit Message的校验脚本:verifyCommit.js (opens new window)
显然,如果每次手动来编写这些是比较麻烦的事情,Vue官方库自己写了校验的脚本。
我们也可以使用一个工具:Commitizen (opens new window),它是一个帮助我们编写规范 commit message 的工具。
安装Commitizen:
npm i commitizen -D
配置交互式提交相关适配器,即可开始使用,下面介绍几种配置,主要是在于修改提示文案。
# 默认提示文案
如果不需要定制Commit提交时的交互提示文案,可以直接安装commitizen 的Angular预设适配器:
npm i -D cz-conventional-changelog
在package.json
中配置:
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
}
或者在根目录下创建.czrc
,并配置:
{
"path": "cz-conventional-changelog"
}
上面两种配置方式二选一即可。都配置时,有限使用.czrc
中的配置。
在package.json
中配置Scripts
"scripts": {
"cz": "cz"
}
此时执行npm run cz
可看到如下提示,按照提示一步步操作即可:
❯ npm run cz
> vue3-code-spec-demo@0.0.0 cz
> cz
cz-cli@4.2.4, cz-conventional-changelog@3.2.0
? Select the type of change that you're committing: (Use arrow keys)
> feat: A new feature
fix: A bug fix
docs: Documentation only changes
style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
refactor: A code change that neither fixes a bug nor adds a feature
perf: A code change that improves performance
test: Adding missing tests or correcting existing tests
(Move up and down to reveal more choices)
# 自定义提示文案 - cz-customizable
如果想自己定义提交规范和提示文案,首先要安装自定义规范约束的包替换第三方规范:
npm i -D cz-customizable
在项目根目录创建.cz-config.js
,并配置规范:
module.exports = {
types: [
{ value: 'init', name: 'init: 初始提交' },
{ value: 'feat', name: 'feat: 增加新功能' },
{ value: 'fix', name: 'fix: 修复bug' },
{ value: 'ui', name: 'ui: 更新UI' },
{ value: '📝docs', name: 'docs: 修改文档' },
{ value: '⚡️perf', name: 'perf: 性能优化' },
{ value: '🎉init', name: '🎉init: 初始提交' },
{ value: '➕add', name: 'add: 添加依赖' },
{ value: '🔨build', name: 'build: 打包' },
{ value: '🔧chore', name: 'chore: 更改配置文件' },
{ value: '👷ci', name: 'ci: CI部署' },
{ value: '🔥del', name: 'del: 删除代码/文件' },
{ value: '♻️refactor', name: 'refactor: 代码重构' },
{ value: 'revert', name: 'revert: 版本回退' },
{ value: 'style', name: 'style: 样式修改不影响逻辑' },
{ value: 'test', name: 'test: 增删测试' },
{ value: 'release', name: 'release: 发布' },
{ value: 'deploy', name: 'deploy: 部署' }
],
scopes: [
{ name: 'components' },
{ name: 'utils' },
{ name: 'styles' },
{ name: 'deps' },
{ name: 'other' }
],
messages: {
type: '选择更改类型:\n',
// 如果allowcustomscopes为true,则使用
scope: '选择一个 scope(可选):\n',
customScope: '请输入自定义的 scope:',
subject: '简短描述:\n',
body: '详细描述. 使用"|"换行:\n',
breaking: 'Breaking Changes列表:\n',
footer: '关闭的issues列表. E.g.: #9527, #666:\n',
confirmCommit: '确认提交?'
},
allowCustomScopes: true,
allowBreakingChanges: ['feat', 'fix']
}
可以在提交信息中加上Emoji,具体的配置规则可见Gihub仓库 (opens new window)。
执行npm run cz
,可看到如下提示,按照提示一步步操作即可:
❯ npx cz
cz-cli@4.2.4, cz-customizable@6.9.0
All lines except first will be wrapped after 100 characters.
? 选择更改类型:
(Use arrow keys)
> init: 初始提交
feat: 增加新功能
fix: 修复bug
ui: 更新UI
refactor: 代码重构
release: 发布
deploy: 部署
(Move up and down to reveal more choices)
# 自定义提示文案- git-cz
也可以使用另外一个库,git-cz (opens new window)来自定义提交规范和提示文案。
它的提交格式如下:
<type>[(<scope>)]: <emoji> <subject>
[BLANK LINE]
[body]
[BLANK LINE]
[breaking changes]
[BLANK LINE]
[footer]
安装库:
npm i -D git-cz
在项目根目录创建changelog.config.js
,并配置规范:
module.exports = {
disableEmoji: false,
format: '{type}{scope}: {emoji}{subject}',
list: [
'feat',
'fix',
'chore',
'test',
'init',
'docs',
'revert',
'refactor',
'style',
'ci',
'perf'
],
maxMessageLength: 80,
minMessageLength: 3,
questions: ['type', 'scope', 'subject', 'body'],
scopes: ['components', 'utils', 'styles', 'deps', 'other', 'test', 'ui'],
types: {
chore: {
description: 'Build process or auxiliary tool changes',
emoji: '🤖',
value: 'chore'
},
ci: {
description: 'CI related changes',
emoji: '🎡',
value: 'ci'
},
docs: {
description: 'Documentation only changes',
emoji: '📝',
value: 'docs'
},
feat: {
description: 'A new feature',
emoji: '🎸',
value: 'feat'
},
fix: {
description: 'A bug fix',
emoji: '🐛',
value: 'fix'
},
perf: {
description: 'A code change that improves performance',
emoji: '⚡️',
value: 'perf'
},
refactor: {
description: 'A code change that neither fixes a bug or adds a feature',
emoji: '💡',
value: 'refactor'
},
release: {
description: 'Create a release commit',
emoji: '🏹',
value: 'release'
},
style: {
description: 'Markup, white-space, formatting, missing semi-colons...',
emoji: '💄',
value: 'style'
},
test: {
description: 'Adding missing tests',
emoji: '💍',
value: 'test'
},
init: {
description: 'project init',
emoji: '🎉',
value: 'init'
},
revert: {
description: 'version back to commit-id',
emoji: '⏪',
value: 'revert'
},
messages: {
type: "Select the type of change that you're committing:",
customScope: 'Select the scope this component affects:',
subject: 'Write a short, imperative mood description of the change:\n',
body: 'Provide a longer description of the change:\n ',
breaking: 'List any breaking changes:\n',
footer: 'Issues this commit closes, e.g #123:',
confirmCommit: 'The packages that this commit has affected\n'
}
}
}
在package.json
中配置:
"config": {
"commitizen": {
"path": "git-cz"
}
}
或者在根目录下创建.czrc
,并配置:
{
"path": "git-cz"
}
上面两种配置方式二选一即可。都配置时,有限使用.czrc
中的配置。
在package.json
中配置Scripts
"scripts": {
"cz": "cz"
}
此时执行npm run cz
可看到如下提示,按照提示一步步操作即可:
> npm run cz
> vue3-code-spec-demo@0.0.0 cz
> cz
cz-cli@4.2.4, git-cz@4.9.0
? Select the type of change that you're committing: (Use arrow keys or type to search)
> 💍 test: Adding missing tests
🎸 feat: A new feature
🐛 fix: A bug fix
🤖 chore: Build process or auxiliary tool changes
✏️ docs: Documentation only changes
💡 refactor: A code change that neither fixes a bug or adds a feature
💄 style: Markup, white-space, formatting, missing semi-colons...
(Move up and down to reveal more choices)
# 提交验证
如果按照cz来规范了提交风格,但是依然可以通过 git commit
按照不规范的格式提交代码。
可以通过 commitlint (opens new window) 来限制提交。
安装依赖:
npm i -D @commitlint/cli @commitlint/config-conventional
- @commitlint/cli 是commit解析CLI
- @commitlint/config-conventional 是默认的约定俗称配置
在根目录下添加commitlint.config.js
上面示例中cz-customizable的校验配置:
// cz-customizable
// eslint-disable-next-line no-undef
module.exports = {
extends: ['@commitlint/config-conventional', 'cz'],
rules: {
'body-leading-blank': [1, 'always'],
'footer-leading-blank': [1, 'always'],
'header-max-length': [2, 'always', 72],
'scope-case': [2, 'always', 'lower-case'],
'subject-case': [
2,
'never',
['sentence-case', 'start-case', 'pascal-case', 'upper-case']
],
'subject-empty': [0],
'subject-full-stop': [2, 'never', '.'],
'type-case': [0],
'type-empty': [0],
'type-enum': [0]
}
}
extends字段可以扩展commitlint的依赖包,比如安装依赖
npm i -D commitlint-config-cz
,然后配置中可再添加上这个配置(省略commitlint-config部分),详见Shareable configuration (opens new window)extends: ['@commitlint/config-conventional', 'cz'],
rules中可自定义规则,每个值由一个name key和数组 value组成,详见Rules (opens new window)。数组有三个元素,如:
[0, 'always', 72]
:- 第一位为 level,可选
0 | 1 | 2
,分别表示disable、warning、error - 第二位为应用与否,可选
always | never
。意思是警告或报错后,是否应用。 - 第三位该rule的值
- 第一位为 level,可选
这是示例中git-cz的校验配置,配置校验更严格:
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
// Header
'header-max-length': [2, 'always', 64],
// <type>枚举
'type-enum': [
2,
'always',
[
'test',
'feat',
'fix',
'chore',
'docs',
'refactor',
'style',
'ci',
'perf'
]
],
// <type> 不能为空
'type-empty': [2, 'never'],
// <type> 格式 小写
'type-case': [2, 'always', 'lower-case'],
// <scope> 不能为空
'scope-empty': [2, 'never'],
// <scope> 格式 小写
'scope-case': [2, 'always', 'lower-case'],
// <subject> 不能为空
'subject-empty': [2, 'never'],
// <subject> 以.为结束标志
// 'subject-full-stop': [2, 'never', '.'],
// <subject> 格式
// 可选值
// 'lower-case' 小写 lowercase
// 'upper-case' 大写 UPPERCASE
// 'camel-case' 小驼峰 camelCase
// 'kebab-case' 短横线 kebab-case
// 'pascal-case' 大驼峰 PascalCase
// 'sentence-case' 首字母大写 Sentence case
// 'snake-case' 下划线 snake_case
// 'start-case' 所有首字母大写 start-case
'subject-case': [
2,
'never',
['sentence-case', 'start-case', 'pascal-case', 'upper-case']
],
// <body> 以空行开头
'body-leading-blank': [1, 'always'],
// <footer> 以空行开头
'footer-leading-blank': [1, 'always']
}
}
然后使Husky添加commit-msg Hook:
npx husky add .husky/commit-msg "npx --no -- commitlint --edit $1"
在提交代码时,使用npm run cz
即可规范提交。
而使用git commit -m "xxx"
提交时会出现错误提示:
❯ git commit -m "测试提交"
> vue3-code-spec-demo@0.0.0 lint
> eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore
⧗ input: 测试提交
✖ subject may not be empty [subject-empty]
✖ type may not be empty [type-empty]
✖ scope may not be empty [scope-empty]
✖ found 3 problems, 0 warnings
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint
husky - commit-msg hook exited with code 1 (error)