一、前言
当项目进行多人开发时,每个人的编码习惯、git提交习惯都不一样,那么就需要一种约定限制,按照统一风格进行代码编写和git提交。
代码规范使用eslint + prettier,git提交规范使用commitlint + husky。下面将详细说明操作步骤。
二、操作步骤
-
安装eslint
pnpm add -D eslint
-
初始化配置eslint
npx eslint --init
(1)选择模式: (To check syntax and find problems)
You can also run this command directly using 'npm init @eslint/config'. ? How would you like to use ESLint? ... To check syntax only > To check syntax and find problems To check syntax, find problems, and enforce code style
(2)选择语言模块: (选JavaScript modules)
? What type of modules does your project use? ... > JavaScript modules (import/export) CommonJS (require/exports) None of these
(3)选择语言框架 (选Vue.js)
? Which framework does your project use? ... React > Vue.js None of these
(4)是否使用ts (视自己情况而定,我这里不用选No)
? Does your project use TypeScript? » No / Yes
(5)代码在哪里运行 (用空格选中 Browser+Node)
? Where does your code run? ... (Press <space> to select, <a> to toggle all, <i> to invert selection) √ Browser √ Node
(6)您希望您的配置文件是什么格式? (选JavaScript)
? What format do you want your config file to be in? ... > JavaScript YAML JSON
(7)您想现在安装它们吗? (选择Yes)
? Would you like to install them now? » No / Yes
(8)您要使用哪个软件包管理器? (选择pnpm)
? Which package manager do you want to use? ... npm yarn > pnpm
(9)安装完成后在项目中会出现.eslint.config.js文件,更改文件为.eslintrc.cjs,并将内容全部替换成如下
// 在rules里面简单的一些配置: // "off" 或 0 - 关闭规则 // "warn" 或 1 - 开启规则,使用警告级别的错误 // "error" 或 2 - 开启规则,使用错误级别的错误 module.exports = { env: { browser: true, es2021: true, node: true }, extends: [ 'eslint:recommended', // 使用推荐的eslint 'plugin:vue/vue3-recommended', // 使用插件支持vue3 // 接入 prettier 的规则 'plugin:prettier/recommended', 'eslint-config-prettier' ], parserOptions: { ecmaVersion: 13, sourceType: 'module', ecmaFeatures: { modules: true, jsx: true }, requireConfigFile: false, parser: '@babel/eslint-parser' }, // eslint-plugin-vue plugins: [ 'vue', // 引入vue的插件 vue <==> eslint-plugin-vue 'prettier' // 引入规范插件 prettier <==> eslint-plugin-prettier ], globals: { defineProps: 'readonly', defineEmits: 'readonly', defineExpose: 'readonly', withDefaults: 'readonly' }, // 这里时配置规则的,自己看情况配置 // 这里可以进行自定义规则配置 // key:规则代号 // value:具体的限定方式 // "off" or 0 - 关闭规则 // "warn" or 1 - 将规则视为一个警告(不会影响退出码),只警告,不会退出程序 // "error" or 2 - 将规则视为一个错误 (退出码为1),报错并退出程序 rules: { // 自定义规则 - 其实上面集成后有很多内置的规则, 这里可以进行规则的一些修改 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 上线环境用打印就报警告, 开发环境关闭此规则 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // debugger可以终止代码执行 'vue/multi-word-component-names': 'off', // 自定义组件名称应该由多单词大驼峰命名组成,防止和html标签冲突 --- 关闭 'vue/max-attributes-per-line': [ 2, // 多个特性的元素应该分多行撰写,每个特性一行 { singleline: 10, multiline: { max: 1 } } ], 'vue/prop-name-casing': [1, 'camelCase'], // 在声明prop的时候,其命名应该始终使用驼峰命名 'vue/require-v-for-key': 1, // 给v-for设置键值,与key结合使用,可以高效的更新虚拟DOM 'vue/no-use-v-if-with-v-for': [ 2, { allowUsingIterationVar: false } ], // 不要把 v-if 和 v-for 用在同一个元素上——因为v-for 比 v-if 具有更高的优先级 'vue/order-in-components': [ 1, { // 组件/实例的选项的顺序 order: [ 'el', 'name', 'parent', 'functional', ['delimiters', 'comments'], ['components', 'directives', 'filters'], 'extends', 'mixins', 'inheritAttrs', 'model', ['props', 'propsData'], 'data', 'computed', 'watch', 'LIFECYCLE_HOOKS', 'methods', ['template', 'render'], 'renderError' ] } ], // // // /// js.规范 / // / 'arrow-spacing': [ 2, { // 在箭头函数之前/之后需要空格 before: true, after: true } ], camelcase: [ 0, { // 需要驼峰命名 properties: 'always' } ], 'comma-dangle': [0, 'never'], // 要求或禁止使用尾随逗号;最后一个属性是不需要逗号 'comma-spacing': [ 2, { // 强制逗号旁边的间距: 左右一个空格 before: false, after: true } ], 'comma-style': [2, 'last'], // 逗号风格 'constructor-super': 2, // 构建方法中使用super方法 curly: [2, 'multi-line'], 'dot-location': [1, 'property'], // 在dot之前和之后强制换行 'eol-last': 2, // 在文件末尾要求或禁止换行 eqeqeq: [1, 'always', { null: 'ignore' }], // 是否使用全等 indent: [ 'off', 2, { // 强制执行一致的缩进 SwitchCase: 1 } ], 'jsx-quotes': [2, 'prefer-single'], // 强制在JSX文件中一致使用单引号 'keyword-spacing': [ 2, { // 关键字前后强制执行一致的间距 before: true, after: true } ], 'new-cap': [ 2, { // 要求构造函数名称以大写字母开头 newIsCap: true, capIsNew: false } ], 'new-parens': 2, // 调用不带参数的函数时需要括号 'no-array-constructor': 2, // 禁止阵列构建器 'no-class-assign': 2, // 禁止修改类声明的变量 'no-cond-assign': 2, // 在条件语句中禁止赋值运算符 'no-const-assign': 2, // 禁止修改使用const声明的变量 'no-control-regex': 0, // 禁止正则表达式中的控制字符 'no-delete-var': 2, // 禁止删除变量 'no-dupe-args': 2, // 在函数定义中禁止重复参数 'no-dupe-class-members': 2, // 禁止在类成员中重复名称 'no-dupe-keys': 2, // 禁止对象重复声明属性 'no-duplicate-case': 2, // 规则禁止重复案例标签 'no-empty-character-class': 2, // 禁止在正则表达式中使用空字符类 'no-empty-pattern': 2, // 不允许空的解构模式 'no-eval': 2, // 禁止使用eval() 'no-ex-assign': 2, // 禁止在catch子句中重新分配异常 'no-extend-native': 2, // 禁止扩展原生对象 'no-extra-bind': 2, // 禁止不必要的功能绑定 'no-extra-boolean-cast': 2, // 禁止不必要的布尔类型转换 'no-extra-parens': [2, 'functions'], // 禁止不必要的括号 'no-func-assign': 2, // 禁止重新分配函数声明 'no-implied-eval': 2, 'no-inner-declarations': [2, 'functions'], // 禁止嵌套块中的变量或函数声明 'no-invalid-regexp': 2, // 禁止在RegExp中使用无效的正则表达式字符串 'no-irregular-whitespace': 2, // 不允许不规则的空白 'no-iterator': 2, // 禁止迭代器 'no-label-var': 2, // 禁止变量名称的标签 'no-labels': [ 2, { allowLoop: false, allowSwitch: false } ], 'no-lone-blocks': 2, // 禁止不必要的嵌套块 'no-mixed-spaces-and-tabs': 2, // 禁止使用混合空格和制表符进行缩进 'no-multi-spaces': 2, // 禁止多个空格 'no-multi-str': 2, // 禁止多行字符串 'no-multiple-empty-lines': [ 2, { // 禁止多个空行 max: 1 } ], 'no-native-reassign': 2, 'no-negated-in-lhs': 2, 'no-new-object': 2, 'no-new-require': 2, 'no-new-symbol': 2, 'no-new-wrappers': 2, 'no-obj-calls': 2, 'no-octal': 2, 'no-octal-escape': 2, 'no-path-concat': 2, 'no-proto': 2, 'no-redeclare': 2, 'no-regex-spaces': 2, 'no-return-assign': [2, 'except-parens'], 'no-self-assign': 2, 'no-self-compare': 2, 'no-sequences': 2, 'no-shadow-restricted-names': 2, 'no-spaced-func': 2, 'no-sparse-arrays': 2, 'no-this-before-super': 2, 'no-throw-literal': 2, 'no-trailing-spaces': 2, 'no-undef': 0, 'no-undef-init': 2, 'no-unexpected-multiline': 2, 'no-unmodified-loop-condition': 2, // 禁止未修改的循环条件 'no-unneeded-ternary': [ 2, { // 当存在更简单的替代方案时,不允许三元运算符 defaultAssignment: false } ], 'no-unreachable': 2, // 返回,抛出,继续和中断语句后禁止无法访问的代码 'no-unsafe-finally': 2, // 禁止finally块中的控制流语句 'no-unused-vars': [ 1, { // 禁止使用未声明的变量 vars: 'all', args: 'none' } ], 'no-useless-call': 2, // 禁止不必要的call()和apply()方法 'no-useless-computed-key': 2, // 禁止在对象上使用不必要的计算属性键 'no-useless-constructor': 2, // 禁止不必要的构造方法 'no-useless-escape': 0, // 禁止不必要的转义用法 'no-whitespace-before-property': 2, // 在属性之前禁止空格 'no-with': 2, 'linebreak-style': [0, 'error', 'windows'], 'one-var': [ 2, { initialized: 'never' } ], 'operator-linebreak': [ 2, 'after', { // 为维护强制执行一致的换行方式 overrides: { '?': 'before', ':': 'before' } } ], 'padded-blocks': [2, 'never'], // 在块内要求或禁止填充 quotes: [ 2, 'single', { avoidEscape: true, allowTemplateLiterals: true } ], semi: [2, 'never'], 'semi-spacing': [ 2, { before: false, after: true } ], 'space-before-blocks': [2, 'always'], // 不要存在多余的块空间 'space-in-parens': [2, 'never'], 'space-infix-ops': 2, 'space-unary-ops': [ 2, { words: true, nonwords: false } ], 'spaced-comment': [ 2, 'always', { markers: ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] } ], 'template-curly-spacing': [2, 'never'], 'use-isnan': 2, 'valid-typeof': 2, 'wrap-iife': [2, 'any'], 'yield-star-spacing': [2, 'both'], yoda: [2, 'never'], 'prefer-const': 1, 'object-curly-spacing': [ 2, 'always', { objectsInObjects: false } ], 'array-bracket-spacing': [2, 'never'], 'prettier/prettier': ['error', { endOfLine: 'auto' }] // 忽略换行格式的检查 } }
-
新建.eslintignore文件,内容如下:
dist node_modules
-
安装vite-plugin-eslint插件,用于配置vite运行时自动检测eslint规范。
pnpm add -D vite-plugin-eslint
-
安装eslint-parser
pnpm add -D @babel/core pnpm add -D @babel/eslint-parser
-
安装prettier
pnpm add -D prettier pnpm add -D eslint-config-prettier // eslint兼容的插件 pnpm add -D eslint-plugin-prettier // eslint的prettier
-
配置vite.config.js
import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import eslintPlugin from 'vite-plugin-eslint' // https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), eslintPlugin({ include: ['src/**/*.js', 'src/**/*.vue', 'src/*.js', 'src/*.vue'], exclude: ['./node_modules/**'], cache: false }) ] })
-
配置 .prettierrc,先修改文件为.prettierrc.cjs,复制内容如下(这里主要配置代码的格式规范的,有些设置要与.eslintrc.js配置一致,防止冲突)
module.exports = { tabWidth: 2, // 使用2个空格缩进 useTabs: false, // 不使用制表缩进,而使用空格 semi: false, // 代码结尾是否加分号 trailingComma: 'none', // 代码末尾不需要逗号 参考 https://prettier.io/docs/en/options.html#prose-wrap singleQuote: true, // 是否使用单引号 printWidth: 120, // 超过多少字符强制换行 arrowParens: 'avoid', // 单个参数的箭头函数不加括号 arg => arg bracketSpacing: true, // 对象大括号内两边是否加空格 { a:0 } endOfLine: 'auto', // 文件换行格式 LF/CRLF quoteProps: 'as-needed', // 对象的key仅在必要时用引号 jsxSingleQuote: false, // jsx不使用单引号,而使用双引号 jsxBracketSameLine: false, // jsx标签的反尖括号需要换行 rangeStart: 0, // 每个文件格式化的范围是文件的全部内容 rangeEnd: Infinity, // 结尾 requirePragma: false, // 不需要写文件开头的 @prettier insertPragma: false, // 不需要自动在文件开头插入 @prettier proseWrap: 'preserve', // 使用默认的折行标准 参考 https://prettier.io/docs/en/options.html#trailing-commas htmlWhitespaceSensitivity: 'css' // 根据显示样式决定html要不要折行 }
-
新建.prettierignore,内容如下:
/dist/* /html/* .local /node_modules/** **/*.svg **/*.sh /public/*
-
添加脚本(在
packjson.json
文件的script
字段中添加命令)
"format": "prettier --write "./**/*.{html,vue,js,ts,json,md}" "
-
配置VScode
(1)安装“ESLint”插件
(2)安装“Prettier ESLint”插件
{ // vscode默认启用了根据文件类型自动设置tabsize的选项 "editor.detectIndentation": false, // 重新设定tabsize "editor.tabSize": 2, // 每次保存的时候自动格式化 "editor.formatOnSave": true, // 每次保存的时候将代码按eslint格式进行修复 "eslint.autoFixOnSave": true, // 添加vue支持 "eslint.validate": [ "javascript", "javascriptreact", { "language": "vue", "autoFix": true } ], // 让prettier使用eslint的代码格式进行校验 "prettier.eslintIntegration": true, "editor.codeActionsOnSave": { "source.fixAll.eslint": true }, "editor.fontLigatures": false, "[jsonc]": { "editor.defaultFormatter": "rvest.vs-code-prettier-eslint" } }
-
配置husky
(1)安装husky
pnpm install -D husky
(2)生成 husky 配置文件
npx husky-init
执行此命令后会在根目录下生成个一个.husky目录,在这个目录下面会有一个pre-commit文件,内容如下。这个文件里面的命令在我们执行commit的时候就会执行。
#!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" pnpm format
-
配置commitlint(配置 git 提交时的 commit 信息,统一提交 git 提交规范)
(1)安装commitlint
pnpm add @commitlint/config-conventional @commitlint/cli -D
(2)在项目根目录下新建 commitlint.config.cjs 文件,并填入如下代码:
module.exports = { extends: ['@commitlint/config-conventional'], // 校验规则 rules: { 'type-enum': [ 2, 'always', ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'chore', 'revert', 'build'] ], 'type-case': [0], 'type-empty': [0], 'scope-empty': [0], 'scope-case': [0], 'subject-full-stop': [0, 'never'], 'subject-case': [0, 'never'], 'header-max-length': [0, 'always', 72] } }
配置说明:
'feat', //新特性、新功能 'fix', //修改bug 'docs', //文档修改 'style', //代码格式修改, 注意不是 css 修改 'refactor', //代码重构 'perf', //优化相关,比如提升性能、体验 'test', //测试用例修改 'chore', //其他修改, 比如改变构建流程、或者增加依赖库、工具等 'revert', //回滚到上一个版本 'build', //编译相关的修改,例如发布版本、对项目构建或者依赖的改动
(3)添加脚本(在
packjson.json
文件的script
字段中添加命令)"commitlint": "commitlint --config commitlint.config.cjs -e -V"
(4)在项目的.husky目录下创建commit-msg文件,表示执行commit时进行校验,内容如下:
#!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" pnpm commitlint
(5)在项目的.husky目录下创建pre-commit文件,表示执行commit前进行代码规范化,内容如下:
#!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" pnpm format
-
当前package.json
{
"name": "web_website_admin",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"prepare": "husky install",
"commitlint": "commitlint --config commitlint.config.cjs -e -V",
"lint": "eslint src",
"fix": "eslint src --fix",
"format": "prettier --write \"./**/*.{html,vue,js,ts,json,md}\" "
},
"dependencies": {
"vue": "^3.4.21"
},
"devDependencies": {
"@babel/core": "^7.24.5",
"@babel/eslint-parser": "^7.24.5",
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@eslint/js": "^9.2.0",
"@vitejs/plugin-vue": "^5.0.4",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-n": "^15.0.0 || ^16.0.0 ",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-vue": "^9.26.0",
"globals": "^15.2.0",
"husky": "^8.0.0",
"prettier": "^3.2.5",
"vite": "^5.2.0",
"vite-plugin-eslint": "^1.8.1"
}
}
三、效果验证
(1)当我们打乱代码,按下ctrl + s保存,会自动根据代码规范进行格式化。
(2)当我们提交git时,提交前会执行pre-commit脚本里的内容,将其代码进行规范化,随后进行提交信息的校验,需按照我们的校验规则进行编写提交信息,否则会显示提交失败。
四、寄语
到这里,项目规范配置完成了,如需源码、资源等,观祝工种号---代码分享站领取哦~