vite + vue3 配置eslint prettier stylelint husky lint-staged husky commitlint
引言
为了项目团队统一编码风格以及对代码的约束,故引入以下依赖及配置。
第一步 安装依赖
依赖包若有兼容性问题,请查看下方具体的版本号
sql
yarn add eslint@8.57.0 --dev
yarn add prettier eslint-config-prettier eslint-config-airbnb-base eslint-plugin-import eslint-plugin-vue eslint-plugin-prettier vite-plugin-eslint --dev
yarn add stylelint stylelint-config-recess-order stylelint-config-recommended-scss stylelint-config-standard
stylelint-config-standard-scss stylelint-config-standard-vue --dev
yarn add lint-staged --dev
yarn add husky @commitlint/cli @commitlint/config-conventional commitizen cz-git --dev
eslint
代码规则定义及检测工具
prettier
代码风格定义及检测工具
eslint-plugin-import
airbnb所需的依赖,检测js import语句是否正确
eslint-config-prettier
配置eslint规则的prettier包,可以禁用 Prettier与 ESLint冲突的规则。
eslint-config-airbnb-base
airbnb风格的代码规范
eslint-plugin-vue
可以对.vue文件的代码进行检查
eslint-plugin-prettier
使用 Prettier风格格式化代码
vite-plugin-eslint
在vite运行时检测代码是否符合eslint规范
stylelint
stylelint 核心库
stylelint-config-recess-order
css 属性的排序(插件包)
stylelint-config-recommended-scss
扩展 stylelint-config-recommended 共享配置,并为 SCSS 配置其规则
stylelint-config-standard
打开额外的规则来执行在规范和一些 CSS 样式指南中发现的通用约定,包括:惯用 CSS 原则,谷歌的 CSS 样式指南,Airbnb 的样式指南,和 @mdo 的代码指南。
stylelint-config-standard-scss
扩展 stylelint-config-standard 共享配置,并为 SCSS 配置其规则
stylelint-config-standard-vue
扩展 stylelint-config-standard 配置,并为 Vue 配置其规则
lint-staged
扫描暂存区的文件
@commitlint/cli @commitlint/config-conventional
校验commit是否符合规范
commitizen
git commit 终端可视化交互工具
与 cz-git 配合使用
cz-git
与commitizen配合使用
第二步 vscode安装扩展及相关配置文件
vs code安装扩展
vscode中安装eslint、prettier、stylelint扩展
项目根目录新建配置文件
.eslintrc.cjs
rust
module.exports = {
root: true,
env: {
browser: true,
node: true,
es6: true,
},
// 指定如何解析语法
parser: 'vue-eslint-parser',
// 优先级低于 parse 的语法解析配置
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
ecmaFeatures: {
jsx: false,
},
},
// 继承某些已有的规则
extends: [
'plugin:vue/vue3-recommended', // 使用插件支持vue3
'airbnb-base',
'plugin:prettier/recommended',
'./.eslintrc-auto-import.json',
],
/**
* "off" 或 0 ==> 关闭规则
* "warn" 或 1 ==> 打开的规则作为警告(不影响代码执行)
* "error" 或 2 ==> 规则作为一个错误(代码不能执行,界面报错)
*/
rules: {
// eslint (http://eslint.cn/docs/rules)
'prettier/prettier': 'error',
'import/extensions': 0,
'prefer-template': 0,
'no-var': 'error', // 要求使用 let 或 const 而不是 var
'no-multiple-empty-lines': ['error', { max: 1 }], // 不允许多个空行
'prefer-const': 'off', // 使用 let 关键字声明但在初始分配后从未重新分配的变量,要求使用 const
'no-use-before-define': 'off', // 禁止在 函数/类/变量 定义之前使用它们
'no-irregular-whitespace': 'off', // 禁止不规则的空白\
'import/no-cycle': 0,
'no-nested-ternary': 0,
'import/prefer-default-export': 0,
'import/no-unresolved': 0,
'prefer-destructuring': 0,
'no-shadow': 0,
'no-param-reassign': 0,
'consistent-return': 0,
'no-case-declarations': 0,
'prefer-promise-reject-errors': 0,
'jsx-a11y/click-events-have-key-events': 0,
'jsx-a11y/no-static-element-interactions': 0,
camelcase: 0,
'import/no-extraneous-dependencies': 0,
'no-underscore-dangle': 0,
'no-debugger': 0,
'no-promise-executor-return': 0,
// vue (https://eslint.vuejs.org/rules)
'vue/script-setup-uses-vars': 'error', // 防止<script setup>使用的变量<template>被标记为未使用,此规则仅在启用该no-unused-vars规则时有效。
'vue/v-slot-style': 'error', // 强制执行 v-slot 指令样式
'vue/no-mutating-props': 'off', // 不允许组件 prop的改变
'vue/no-v-html': 'off', // 禁止使用 v-html
'vue/custom-event-name-casing': 'off', // 为自定义事件名称强制使用特定大小写
'vue/attributes-order': 'off', // vue api使用顺序,强制执行属性顺序
'vue/one-component-per-file': 'off', // 强制每个组件都应该在自己的文件中
'vue/html-closing-bracket-newline': 'off', // 在标签的右括号之前要求或禁止换行
'vue/max-attributes-per-line': 'off', // 强制每行的最大属性数
'vue/multiline-html-element-content-newline': 'off', // 在多行元素的内容之前和之后需要换行符
'vue/singleline-html-element-content-newline': 'off', // 在单行元素的内容之前和之后需要换行符
'vue/attribute-hyphenation': 'off', // 对模板中的自定义组件强制执行属性命名样式
'vue/require-default-prop': 'off', // 此规则要求为每个 prop 为必填时,必须提供默认值
'vue/multi-word-component-names': 'off', // 要求组件名称始终为 "-" 链接的单词
'vue.prefer-template': 'off',
'vuejs-accessibility/click-events-have-key-events': 'off',
},
};
.eslintignore
arduino
dist
node_modules
public
.husky
.bin
docs
html
.vscode
.idea
*.sh
*.md
.prettierrc.json
这里建议使用json配置文件而不是cjs或js配置文件,经测试不同版本可能会出现问题
json
{
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"quoteProps": "as-needed",
"jsxSingleQuote": false,
"trailingComma": "es5",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"bracketSameLine": false,
"arrowParens": "avoid",
"endOfLine": "auto",
"embeddedLanguageFormatting": "auto",
"vueIndentScriptAndStyle": true,
"singleAttributePerLine": false,
"htmlWhitespaceSensitivity": "css",
"requirePragma": false,
"insertPragma": false,
"proseWrap": "preserve"
}
.prettierignore
arduino
dist
build
node_modules
public
.husky
.bin
docs
html
.vscode
.idea
*.sh
*.md
.stylelintrc.cjs
java
// @see https://stylelint.bootcss.com/
module.exports = {
extends: [
'stylelint-config-standard', // 配置stylelint拓展插件
'stylelint-config-html/vue', // 配置 vue 中 template 样式格式化
'stylelint-config-standard-scss', // 配置stylelint scss插件
'stylelint-config-recommended-vue/scss', // 配置 vue 中 scss 样式格式化
'stylelint-config-recess-order', // 配置stylelint css属性书写顺序插件,
// 'stylelint-config-prettier', // 配置stylelint和prettier兼容, 注意stylelint大于等于v15是已经不需要此插件
],
overrides: [
{
files: ['**/*.(scss|css|vue|html)'],
customSyntax: 'postcss-scss',
},
{
files: ['**/*.(html|vue)'],
customSyntax: 'postcss-html',
},
],
ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts', '**/*.json', '**/*.md', '**/*.yaml'],
/**
* null => 关闭该规则
* always => 必须
*/
rules: {
'font-family-no-missing-generic-family-keyword': null,
'value-keyword-case': null, // 在 css 中使用 v-bind,不报错
'no-descending-specificity': null, // 禁止在具有较高优先级的选择器后出现被其覆盖的较低优先级的选择器
'function-url-quotes': 'always', // 要求或禁止 URL 的引号 "always(必须加上引号)"|"never(没有引号)"
'no-empty-source': null, // 关闭禁止空源码
'selector-class-pattern': null, // 关闭强制选择器类名的格式
'property-no-unknown': null, // 禁止未知的属性(true 为不允许)
// 'block-opening-brace-space-before': 'always', //大括号之前必须有一个空格或不能有空白符
'value-no-vendor-prefix': null, // 关闭 属性值前缀 --webkit-box
'property-no-vendor-prefix': null, // 关闭 属性前缀 -webkit-mask
'scss/dollar-variable-pattern': null,
'scss/at-mixin-pattern': null,
'selector-pseudo-class-no-unknown': [
// 不允许未知的选择器
true,
{
ignorePseudoClasses: ['global', 'v-deep', 'deep'], // 忽略属性,修改element默认样式的时候能使用到
},
],
},
};
.stylelintignore
bash
/.husky/*
/.vscode/*
/bin
/node_modules/*
/docs/*
/html/*
/dist/*
/public/*
/scripts/*
.lintstagedrc.json
css
{
"src/**/*.{vue,js}": [
"npm run prettier",
"npm run eslint"
],
"src/**/*.{vue,scss,css,less}": [
"npm run stylelint:out"
]
}
.commitlintrc.cjs
css
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'body-leading-blank': [1, 'always'],
'body-max-line-length': [2, 'always', 100],
'footer-leading-blank': [1, 'always'],
'footer-max-line-length': [1, 'always', 100],
'header-max-length': [2, 'always', 100],
'subject-case': [2, 'never', ['sentence-case', 'start-case', 'pascal-case', 'upper-case']],
'subject-empty': [2, 'never'],
'subject-full-stop': [2, 'never', '.'],
'type-case': [2, 'always', 'lower-case'],
'type-empty': [2, 'never'],
'type-enum': [
2,
'always',
[
'build',
'chore',
'ci',
'docs',
'feat',
'fix',
'perf',
'refactor',
'revert',
'style',
'test',
'conflict',
'fonts',
'delete',
'stash',
],
],
},
};
.czrc
swift
{
"path": "cz-git",
"messages": {
"type": "选择你要提交的类型:",
"scope": "选择一个提交范围(可选):",
"customScope": "请输入自定义的提交范围:",
"subject": "填写简短精炼的变更描述:\n",
"body": "填写更加详细的变更描述(可选)。使用"|"换行:\n",
"breaking": "列举非兼容性重大的变更(可选)。使用"|"换行:\n",
"footerPrefixesSelect": "选择关联issue前缀(可选):",
"customFooterPrefix": "输入自定义issue前缀:",
"footer": "列举关联issue (可选)例如: #31, #I3244:\n",
"generatingByAI": "正在通过 AI 生成你的提交简短描述...",
"generatedSelectByAI": "选择一个 AI 生成的简短描述:",
"confirmCommit": "是否提交或修改commit?"
},
"types": [
{
"value": "feat",
"name": "feat: ✨ 新增功能",
"emoji": ":sparkles:"
},
{
"value": "fix",
"name": "fix: 🐛 修复缺陷",
"emoji": ":bug:"
},
{
"value": "docs",
"name": "docs: 📚 文档变更",
"emoji": ":books:"
},
{
"value": "style",
"name": "style: 💄 代码格式(不影响功能,例如空格、分号等格式修正)",
"emoji": ":lipstick:"
},
{
"value": "refactor",
"name": "refactor: 📦 代码重构(不包括 bug 修复、功能新增)",
"emoji": ":package:"
},
{
"value": "perf",
"name": "perf: 🚀 性能优化",
"emoji": ":rocket:"
},
{
"value": "conflict",
"name": "conflict: 🧰 修改冲突",
"emoji": ":rewind:"
},
{
"value": "test",
"name": "test: ✅ 添加疏漏测试或已有测试改动",
"emoji": ":white_check_mark:"
},
{
"value": "build",
"name": "build: 🔧 构建流程、外部依赖变更(如升级 npm 包、修改 vite 配置等)",
"emoji": ":wrench:"
},
{
"value": "ci",
"name": "ci: 🎡 修改 CI 配置、脚本",
"emoji": ":ferris_wheel:"
},
{
"value": "revert",
"name": "revert: ⏪️ 回滚 commit",
"emoji": ":rewind:"
},
{
"value": "chore",
"name": "chore: 🔨 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)",
"emoji": ":hammer:"
},
{
"value": "fonts",
"name": "fonts: 🔠 字体文件更新",
"emoji": ":capital_abcd:"
},
{
"value": "delete",
"name": "delete: 🆑 删除文件",
"emoji": ":cl:"
}
],
"useEmoji": true,
"emojiAlign": "center",
"useAI": false,
"aiNumber": 1,
"themeColorCode": "",
"scopes": [],
"allowCustomScopes": true,
"allowEmptyScopes": true,
"customScopesAlign": "bottom",
"customScopesAlias": "custom",
"emptyScopesAlias": "empty",
"upperCaseSubject": false,
"markBreakingChangeMode": false,
"allowBreakingChanges": [
"feat",
"fix"
],
"breaklineNumber": 100,
"breaklineChar": "|",
"skipQuestions": [],
"issuePrefixes": [
{
"value": "closed",
"name": "closed: ISSUES has been processed"
}
],
"customIssuePrefixAlign": "top",
"emptyIssuePrefixAlias": "skip",
"customIssuePrefixAlias": "custom",
"allowCustomIssuePrefix": true,
"allowEmptyIssuePrefix": true,
"confirmColorize": true,
"minSubjectLength": 0,
"defaultBody": "",
"defaultIssues": "",
"defaultScope": "",
"defaultSubject": ""
}
package.json
json
scripts: {
// 开发环境运行项目,会自动读取.env.development配置
"dev": "vite",
// 生产环境打包项目到dist目录,会自动读取.env.production
"build:prod": "vite build",
// 预发环境打包项目到dist目录,会自动读取.env.staging
"build:stage": "vite build --mode staging",
// 在本机跑个server来运行dist目录
"preview": "vite preview",
// stylelint检测文件并自动fix
"stylelint:fix": "stylelint "src/**/*.{html,vue,css,scss}" --fix",
// stylelint检测文件并将错误输出到.stylelint-output.txt
"stylelint:out": "stylelint "src/**/*.{html,vue,css,scss}" -o .stylelint-output.txt -f string",
// prettier检测文件
"prettier": "prettier --check "src/**/*.{js,ts,json,css,less,scss,vue,html,md}"",
// prettier检测文件并自动fix
"prettier:fix": "prettier --log-level error --write "src/**/*.{js,ts,json,css,less,scss,vue,html,md}"",
// eslint检测文件
"eslint": "eslint --ext .js,.vue ./src vite.config.js ",
// eslint检测文件并自动fix
"eslint:fix": "eslint --ext .js,.vue --fix ./src vite.config.js",
// eslint检测文件并将错误输出到指定.eslint-ouput.html
"eslint:out": "eslint --ext .js,.vue -o .eslint-output.html -f html ./src vite.config.js",
// eslint检测文件并将错误输出到指定.eslint-ouput.html,并且自动修复
"eslint:fixout": "eslint --ext .js,.vue --fix -o .eslint-output.html -f html ./src vite.config.js",
// lint-staged 检测git暂存区的文件
"lint-staged": "lint-staged",
// 同git commit
"cm": "git-cz",
// 一般无需关注
"commitlint": "commitlint -e -V",
// husky 初始化
"prepare": "husky"
}
git core.autocrlf的设置
不同系统下换行符不同,具体问题可以自行百度,这里不做赘述。具体配置如下
csharp
#windows下输入命令
git config --global core.autocrlf true
#mac下输入命令
git config --global core.autocrlf input
#查看是否设置成功
git config --global --get core.autocrlf
版本依赖
除了eslint,其他依赖包版本皆为当下最新版本。经测试eslint v9与其他依赖包可能会出现兼容性问题,当然也可能是我没有配置正确,暂时未对v9做深入。
perl
"devDependencies": {
"@commitlint/cli": "^19.2.2",
"@commitlint/config-conventional": "^19.2.2",
"commitizen": "^4.3.0",
"cz-git": "^1.9.1",
"eslint": "8.57.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-vue": "^9.25.0",
"husky": "^9.0.11",
"lint-staged": "^15.2.2",
"prettier": "^3.2.5",
"stylelint": "^16.3.1",
"stylelint-config-recess-order": "^5.0.1",
"stylelint-config-recommended-scss": "^14.0.0",
"stylelint-config-standard": "^36.0.0",
"stylelint-config-standard-scss": "^13.1.0",
"stylelint-config-standard-vue": "^1.0.0",
"vite": "5.0.4",
"vite-plugin-eslint": "^1.8.1",
}
注意事项
注意文件的命名的问题,因为我的package.json里指定了type: "module", 所以.js文件都会当作es module模块被处理。如果你不想以es module的方式来书写配置,你应当以.cjs扩展名来命名配置文件。