项目初始化规范配置:(Prettier、EsLint、StyleLint、CommitLint)
摘要:
包含js格式检查,css样式检查,自动根据规则格式化,提交检查。(Prettier、EsLint、StyleLint、CommitLint、husky、lint-staged、@commitlint/cz-commitlint、commitizen、cz-git、czg)
常见问题
配置过程中可能出现的问题,可以先跳过此部分,出现问题时再回来查看。
配置文件不生效
- 先检查重启编辑器后是否生效。
- 如果生效,可以使用下面三种方法:
- ctrl+shift+p打开控制台,输入“Reload Window”重新加载窗口。
- 重启vscode。
- 配置文件使用json格式。
- 不生效,检查配置文件名是否正确,检查配置文件是否有语法错误。
换行符问题
- 不同平台创建文件,默认换行符可能不同:lf、crlf。当使用window开发时,默认换行符为crlf。而如果在prettier配置中设置了换行符为lf,stylelint会报错。
解决方法
- 安装vscode插件:EditorConfig for VS Code
- 在项目根目录创建
.editorconfig文件,内容如下:(根据实际情况修改) - 这样保存文件时,vscode会根据
.editorconfig文件的配置,自动将换行符转换为配置内容。
bash
root = true
[*]
charset=utf-8
end_of_line=lf
insert_final_newline=true
indent_style=space
indent_size=2
max_line_length = 100
[*.{yml,yaml,json}]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
Prettier 配置
安装vscode插件
- 安装Prettier - Code formatter插件
- 修改vscode设置:
json
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.fixAll.tslint": "explicit",
"source.fixAll.stylelint": "explicit"
},
}
安装依赖
npm install prettier --save-dev
配置文件
.prettierrc.json,根据实际情况修改.prettierignore,忽略配置,根据实际情况修改
js
{
"semi": false,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"bracketSpacing": true,
"arrowParens": "always",
"endOfLine": "lf",
"jsxSingleQuote": false,
"singleAttributePerLine": false,
"htmlWhitespaceSensitivity": "css",
"proseWrap": "never",
"overrides": [
{
"files": ["*.json", "*.yml", "*.yaml"],
"options": { "printWidth": 80 }
}
]
}
EsLint 配置
EsLint版本:
^9
安装vscode插件
- 安装EsLint插件
- 修改vscode设置:
json
{
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact", "vue"],
}
依赖说明
- eslint:eslint核心
- globals:全局变量配置
- eslint-config-prettier:eslint prettier配置(解决二者冲突)
- @eslint/js:js配置
- typescript-eslint:ts配置
- eslint-plugin-*:eslint插件,根据实际情况安装,常用插件有:
- eslint-plugin-react:react插件
- eslint-plugin-react-hooks:react hooks插件
- @next/eslint-plugin-next:nextjs插件
- eslint-plugin-vue:vue插件
- @vue/eslint-config-typescript:适合vue的ts规则配置
- @vue/eslint-config-prettier:适合vue的prettier配置
- @nuxt/eslint:nuxt插件
- eslint-plugin-import:ESM import插件
注意:prettier放到最后,用于覆盖与EsLint冲突的配置。
JS简单配置
js
import js from '@eslint/js'
import globals from 'globals'
import { defineConfig, globalIgnores } from 'eslint/config'
import prettier from 'eslint-config-prettier'
export default defineConfig([
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
{
files: ['**/*.{js,mjs,cjs}'],
plugins: { js },
extends: ['js/recommended'],
languageOptions: { globals: globals.browser },
},
{
rules: {
// 自己的规则
}
},
prettier,
])
TS简单配置
js
import js from '@eslint/js'
import globals from 'globals'
import tseslint from 'typescript-eslint'
import { defineConfig, globalIgnores } from 'eslint/config'
import prettier from 'eslint-config-prettier'
export default defineConfig([
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
{
files: ['**/*.{js,mjs,cjs,ts,mts,cts}'],
plugins: { js },
extends: ['js/recommended'],
languageOptions: { globals: globals.browser },
},
tseslint.configs.recommended,
{
rules: {
// 自己的规则
}
},
prettier,
])
Vue+JS简单配置
js
import { defineConfig, globalIgnores } from 'eslint/config'
import globals from 'globals'
import js from '@eslint/js'
import pluginVue from 'eslint-plugin-vue'
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
export default defineConfig([
{
name: 'app/files-to-lint',
files: ['**/*.{js,mjs,jsx,vue}'],
},
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
{
languageOptions: {
globals: {
...globals.browser,
},
},
},
js.configs.recommended,
...pluginVue.configs['flat/essential'],
{
rules: {
// 自己的规则
}
},
skipFormatting,
])
Vue+TS简单配置
js
import { globalIgnores } from 'eslint/config'
import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript'
import pluginVue from 'eslint-plugin-vue'
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
export default defineConfigWithVueTs(
{
name: 'app/files-to-lint',
files: ['**/*.{ts,mts,tsx,vue}'],
},
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
pluginVue.configs['flat/essential'],
vueTsConfigs.recommended,
{
rules: {
// 自己的规则
}
},
skipFormatting,
)
Nuxtjs简单配置
js
// nuxt.config.ts
export default defineNuxtConfig({
modules: [
'@nuxt/eslint'
],
eslint: {
// options here
}
})
// eslint.config.mjs
import withNuxt from './.nuxt/eslint.config.mjs'
export default withNuxt(
{
rules: {
// 自己的规则
}
}
)
React+JS简单配置
js
import js from '@eslint/js'
import globals from 'globals'
import pluginReact from 'eslint-plugin-react'
import { defineConfig, globalIgnores } from 'eslint/config'
import prettier from 'eslint-config-prettier'
export default defineConfig([
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
{
files: ['**/*.{js,mjs,cjs,jsx}'],
plugins: { js },
extends: ['js/recommended'],
languageOptions: { globals: globals.browser },
},
pluginReact.configs.flat.recommended,
{
rules: {
// 自己的规则
}
},
prettier,
])
React+TS简单配置
js
import js from '@eslint/js'
import globals from 'globals'
import tseslint from 'typescript-eslint'
import pluginReact from 'eslint-plugin-react'
import { defineConfig, globalIgnores } from 'eslint/config'
import prettier from 'eslint-config-prettier'
export default defineConfig([
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
{
files: ['**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
plugins: { js },
extends: ['js/recommended'],
languageOptions: { globals: globals.browser },
},
tseslint.configs.recommended,
pluginReact.configs.flat.recommended,
{
rules: {
// 自己的规则
}
},
prettier,
])
Next简单配置
js
import { defineConfig, globalIgnores } from 'eslint/config'
import nextVitals from 'eslint-config-next/core-web-vitals'
import nextTs from 'eslint-config-next/typescript'
import prettier from 'eslint-config-prettier'
export default defineConfig([
...nextVitals,
...nextTs,
prettier,
globalIgnores([
'.next/**',
'out/**',
'build/**',
'next-env.d.ts',
]),
{
rules: {
// 自己的规则
},
},
])
import 检查、排序
js
import { defineConfig } from 'eslint/config'
import importPlugin from 'eslint-plugin-import'
export default defineConfig([
// ...
importPlugin.flatConfigs.recommended,
{
rules: {
'import/order': [
'error',
{
// 组排序:builtin > external > parent > sibling > index
// Node.js内置模块 > 第三方模块 > 项目内部模块 > 父级目录 > 同级目录 > 当前目录的index文件
groups: ['builtin', 'external', 'parent', 'sibling', 'index'],
// 首字母排序,忽略大小写
alphabetize: { order: 'asc', caseInsensitive: true },
},
],
},
},
])
StyleLint配置
安装vscode插件
- 安装StyleLint插件
- 修改vscode设置:
json
{
"stylelint.validate": ["css", "scss", "less", "vue", "html"],
}
依赖说明
- stylelint:stylelint核心
- stylelint-prettier:stylelint prettier配置(解决二者冲突)
- stylelint-config-*:stylelint插件,根据实际情况安装,常用插件有:
- stylelint-config-standard-scss:标准的scss配置
- stylelint-config-html:html配置(支持很多类型文件,具体看源码)
- stylelint-config-standard-vue:vue配置
- stylelint-config-recess-order:属性排序配置
安装依赖
根据上方说明和自己需要进行安装,下方为全部安装命令。
bash
npm install stylelint stylelint-config-standard-scss stylelint-config-html stylelint-config-standard-vue stylelint-config-recess-order stylelint-prettier --save-dev
配置文件
stylelint.config.mjs,根据实际情况修改.stylelintignore,忽略配置,根据实际情况修改
js
import propertyGroups from 'stylelint-config-recess-order/groups'
/** @type {import('stylelint').Config} */
export default {
extends: [
// 标准配置(包含scss配置)
'stylelint-config-standard-scss',
// html配置(支持很多类型文件,具体看源码)
'stylelint-config-html',
// vue配置
'stylelint-config-standard-vue',
// 属性排序配置
'stylelint-config-recess-order',
// prettier配置
'stylelint-prettier/recommended',
],
rules: {
'order/properties-order': propertyGroups.map((group) => ({
...group,
// 此处覆盖默认排序
})),
},
}
更多插件及扩展
查看官方文档:Awesome Stylelint
CommitLint配置
这些规范在git中使用,配置前请先确认项目是否已经初始化git仓库。
依赖说明
- husky:提供git钩子的工具
- lint-staged:在git暂存文件上运行格式化或检查。(虽然eslint、stylelint等工具也能对文件进行检查,但lint-staged只在git暂存文件上运行,避免对未更改的文件进行检查,提高效率。)
- @commitlint/cli:对提交信息进行检查
- @commitlint/config-conventional:符合conventional commit规范的默认配置,可在此基础上扩展。
三者配合下,在
git要提交时,husky提供钩子,lint-staged在husky提供的pre-commit钩子上运行代码格式化或检查,@commitlint/cli在husky提供的commit-msg钩子上运行提交信息是否符合规范检查。
安装依赖
bash
npm install husky lint-staged @commitlint/cli @commitlint/config-conventional --save-dev
配置文件
- 初始化husky
bash
npx husky init
此命令会创建.husky目录,并在其中创建pre-commit脚本,并更新 package.json 中的 prepare 脚本。
lint-staged.config.mjs,根据实际情况修改
js
/**
* @filename: lint-staged.config.mjs
* @type {import('lint-staged').Configuration}
*/
export default {
'*.{js,jsx,ts,tsx}': ['prettier --write', 'eslint --fix'],
'{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': ['prettier --write--parser json'],
'package.json': ['prettier --write'],
'*.vue': ['prettier --write', 'eslint --fix', 'stylelint --fix'],
'*.{css,scss,less,styl,html}': ['prettier --write', 'stylelint --fix'],
'*.md': ['prettier --write'],
}
- 更新
.husky/commit-msg文件,根据实际情况修改
bash
# 选择任何一种方式都行
# 指定配置文件(当文件名不符合默认规则时)
npx lint-staged --config lint-staged.config.mjs
# 简单配置
npx lint-staged
# 使用pnpm
pnpm exec lint-staged
# 当然也可以把这个放在`package.json`的`scripts`中,然后在`pre-commit`钩子中运行
npm run staged
commitlint.config.mjs,根据实际情况修改
js
/**
* @filename: commitlint.config.mjs
* @type {import('@commitlint/types').UserConfig}
*/
export default {
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',
],
],
},
}
- 更新
.husky/commit-msg文件,根据实际情况修改
bash
npx --no -- commitlint --edit "$1"
添加commit交互式提示
两种推荐方案,都差不多。
1. 使用@commitlint/cz-commitlint插件
安装依赖
bash
npm i -D @commitlint/cz-commitlint commitizen inquirer@9
修改package.json,添加commitizen配置
json
{
"scripts": {
"commit": "git-cz"
},
"config": {
"commitizen": {
"path": "@commitlint/cz-commitlint"
}
}
}
修改commitlint.config.mjs,添加prompt配置(根据实际情况修改)
js
/**
* @filename: commitlint.config.mjs
* @type {import('@commitlint/types').UserConfig}
*/
export default {
extends: ['@commitlint/config-conventional'],
rules: {
// 自定义规则
},
prompt: {
settings: {},
messages: {
skip: '回车跳过',
max: '最多 %d 个字符',
min: '至少 %d 个字符',
emptyWarning: '不能为空',
upperLimitWarning: '超过上限',
lowerLimitWarning: '低于下限',
},
questions: {
type: {
description: '选择你要提交的变更类型:',
enum: {
feat: {
description: '新增功能',
title: '新增功能',
emoji: '✨',
},
fix: {
description: '修复 bug',
title: '修复 bug',
emoji: '🐛',
},
docs: {
description: '文档变更',
title: '文档变更',
emoji: '📚',
},
style: {
description: '代码格式变更,不影响代码含义(空格、格式化、缺少分号等)',
title: '代码格式变更',
emoji: '💎',
},
refactor: {
description: '代码变更,既不修复 bug 也不新增功能',
title: '代码重构',
emoji: '📦',
},
perf: {
description: '性能优化',
title: '性能优化',
emoji: '🚀',
},
test: {
description: '添加缺失的测试或修正现有的测试',
title: '测试',
emoji: '🚨',
},
build: {
description: '构建系统或外部依赖项的变更(例如 scopes: gulp, broccoli, npm)',
title: '构建系统变更',
emoji: '🛠',
},
ci: {
description:
'CI 配置文件或脚本的变更(例如 scopes: Travis, Circle, BrowserStack, SauceLabs)',
title: 'CI 配置变更',
emoji: '⚙️',
},
chore: {
description: '其他不修改 src 或 test 文件的变更',
title: '其他变更',
emoji: '♻️',
},
revert: {
description: '回滚之前的提交',
title: '回滚提交',
emoji: '🗑',
},
},
},
scope: {
description: '变更的范围(例如组件或文件名)',
},
subject: {
description: '变更的简短描述( imperative tense)',
},
body: {
description: '变更的详细描述',
},
isBreaking: {
description: '是否有重大变更?',
},
breakingBody: {
description: '重大变更提交需要包含变更描述。请输入变更描述的详细信息',
},
breaking: {
description: '重大变更的描述',
},
isIssueAffected: {
description: '是否有影响已打开问题的变更?',
},
issuesBody: {
description: '如果有影响已打开问题的变更,提交需要包含变更描述。请输入变更描述的详细信息',
},
issues: {
description: '添加影响已打开问题的变更引用(例如 "fix #123", "re #123".)',
},
},
},
}
使用
bash
git add .
npm run commit
2. 使用cz-git插件(推荐)
安装依赖
bash
npm i -D commitizen cz-git czg
修改package.json,添加commitizen配置
json
{
"scripts": {
"commit": "git-cz",
"czg": "czg"
},
"config": {
"commitizen": {
"path": "node_modules/cz-git"
}
}
}
修改commitlint.config.mjs,添加prompt配置(根据实际情况修改)
js
// 所有范围(可写死,也可动态计算,比如pnpm的workspace,通过读取pnpm-workspace.yaml文件获取)
const scopes = []
// 有改变的范围(动态计算,比如git status --porcelain || true)
const scopesChange = []
/**
* @filename: commitlint.config.mjs
* @type {import('cz-git').UserConfig}
*/
export default {
extends: ['@commitlint/config-conventional'],
rules: {
// 自定义规则
},
prompt: {
// 常用别名:通过 `npm run czg :别名` 使用,直接提交,不再有后续交互
// 如 `npm run czg :f`、`npm run czg :r` 等
alias: {
f: 'docs: 修复拼写错误',
r: 'docs: 更新README.MD',
s: 'style: 更新代码格式',
b: 'build: 新的生产版本',
c: 'chore: 更新配置文件',
w: 'wip: 功能开发中',
},
scopes: [...scopes],
defaultScope: scopesChange,
customScopesAlign: scopesChange.length ? 'bottom' : 'top',
enableMultipleScopes: true,
scopeEnumSeparator: ',',
customScopesAlias: '以上都不是?我要自定义',
emptyScopesAlias: '跳过,不填写',
allowCustomIssuePrefix: false,
allowEmptyIssuePrefix: false,
typesAppend: [
{ value: 'wip', name: 'wip: 正在开发中' },
{ value: 'workflow', name: 'workflow: 工作流程改进' },
{ value: 'types', name: 'types: 类型定义文件修改' },
],
messages: {
type: '选择你要提交的类型 :',
scope: '选择一个提交范围 (可选):',
customScope: '请输入自定义的提交范围 :',
subject: '填写简短精炼的变更描述 :\n',
body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n',
breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n',
footerPrefixsSelect: '选择关联issue前缀 (可选):',
customFooterPrefixs: '输入自定义issue前缀 :',
footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
generatingByAI: '生成你的AI提交主题……',
generatedSelectByAI: '由人工智能选择生成合适的主题:',
confirmCommit: '是否提交或修改commit ?',
},
types: [
{ value: 'feat', name: 'feat: 新增功能', emoji: ':sparkles:' },
{ value: 'fix', name: 'fix: 修复缺陷(bug 修复)', emoji: ':bug:' },
{ value: 'docs', name: 'docs: 文档变更', emoji: ':memo:' },
{
value: 'style',
name: 'style: 代码格式(修改空白字符,补全缺失的分号等)',
emoji: ':lipstick:',
},
{
value: 'refactor',
name: 'refactor: 代码重构(既没有新增功能,也没有修复 bug)',
emoji: ':recycle:',
},
{ value: 'perf', name: 'perf: 性能优化', emoji: ':zap:' },
{
value: 'test',
name: 'test: 添加疏漏测试或已有测试改动',
emoji: ':white_check_mark:',
},
{
value: 'build',
name: 'build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)',
emoji: ':package:',
},
{ value: 'ci', name: 'ci: 修改 CI 配置、脚本', emoji: ':ferris_wheel:' },
{ value: 'revert', name: 'revert: 回滚 commit', emoji: ':rewind:' },
{
value: 'chore',
name: 'chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)',
emoji: ':hammer:',
},
{ value: 'wip', name: 'wip: 正在开发中' },
{ value: 'workflow', name: 'workflow: 工作流程改进' },
{ value: 'types', name: 'types: 类型定义文件修改' },
],
useEmoji: true,
emojiAlign: 'center',
emptyIssuePrefixAlias: '跳过',
customIssuePrefixAlias: '自定义前缀',
},
}
使用
bash
git add .
npm run commit # 交互式提交
npm run czg :f # 使用别名快速提交
评论
0条评论
暂无内容,去看看其他的吧~




