前端工程化之 commitlint + husky 实现 git 提交规范化 编写规范提示
安装 husky 和 lint-staged
husky 可以用于实现各种 git Hook。这里主要用到 pre-commit 这个 hook,在执行 commit 之前,运行一些自定义操作
lint-staged 用于对 git 暂存区中的文件执行代码检测
npm i husky lint-staged -D
Prettier 配置
根目录下创建 .prettierrc.js 文件
module.exports = { // 一行最多 100 字符 printWidth: 100, // 不使用缩进符,而使用空格 useTabs: false, // 使用 2 个空格缩进 tabWidth: 2, tabSize: 2, // 行尾需要有分号 semi: true, // 使用单引号 singleQuote: true, // jsx 不使用单引号,而使用双引号 jsxSingleQuote: false, // 末尾不需要逗号 'es5' none trailingComma: 'es5', // 大括号内的首尾需要空格 bracketSpacing: true, // jsx 标签的反尖括号需要换行 jsxBracketSameLine: false, // 在单个箭头函数参数周围加上括号<avoid|always> arrowParens: 'avoid', // 不需要写文件开头的 @prettier requirePragma: false, // 不需要自动在文件开头插入 @prettier insertPragma: false, // 使用默认的折行标准 proseWrap: 'preserve', // 换行符使用 lf 结尾是 \n \r \n\r auto endOfLine: 'lf', vueIndentScriptAndStyle: true, };
配置好 Pretteir 文件后 可直接使用 commitizen init cz-conventional-changelog -D --save-exact 指令在package,json 文件中生成命令

Eslint 配置
npm i eslint-plugin-react eslint-plugin-react-native -D
npm i eslint eslint-plugin-html eslint-plugin-vue babel-eslint -D
根目录下创建 .eslintrc.js 文件
module.exports = { root: true, // parser: 'babel-eslint', env: { node: true, }, // extends: ["plugin:vue/base", "plugin:vue/recommended"], extends: ['plugin:vue/base'], parserOptions: { parser: 'babel-eslint', }, plugins: ['html', 'vue'], rules: { /* "off"或者0 //关闭规则关闭 "warn"或者1 //在打开的规则作为警告(不影响退出代码) "error"或者2 //把规则作为一个错误(退出代码触发时为1) */ 'no-var': 'error', // 禁止使用var 'prefer-const': 'error', // 建议使用const 'no-const-assign': 'error', // 禁止修改使用const(no-const-assign)声明的变量 'object-shorthand': 'error', // 方法属性值简写 'quote-props': ['error', 'as-needed'], // 只对那些无效的标示使用引号 '' 'no-array-constructor': 'error', // 数组要求字面量赋值 'no-new-object': 'error', // 对象使用字面值创建对象 'array-callback-return': 'error', // 在数组方法的回调中强制执行 'prefer-destructuring': [ 'error', { array: true, object: true, }, { enforceForRenamedProperties: false, }, ], // 用对象的解构赋值来获取和使用对象某个或多个属性值 quotes: ['error', 'single'], // string 统一用单引号 '' 'prefer-template': 'error', // 建议使用模板字符串 'no-eval': 'error', // 禁止使用eval 'no-useless-escape': 'error', // 不要使用不必要的转义字符 'func-style': 'error', // 用命名函数表达式而不是函数声明 const func=()=>{} 'prefer-rest-params': 'error', // 建议使用rest参数而不是参数 'space-before-function-paren': ['error', 'never'], // 函数前不允许使用空格或 'space-before-blocks': ['error', 'always'], // 块前需要空格 'no-param-reassign': 'error', // 不允许重新分配函数参数 'prefer-spread': 'error', // 建议使用spread语法而不是.apply() 'prefer-arrow-callback': 'error', // 建议使用箭头函数 'arrow-spacing': 'error', // 箭头函数的箭头前后需要空格 // "arrow-parens": ["error", "always"], // 在arrow函数参数中需要paren 'arrow-body-style': ['error', 'always'], // 在箭头函数体中需要大括号 'no-confusing-arrow': ['error', { allowParens: true }], // 不允许箭头函数与比较混淆 'no-useless-constructor': 'error', // 不允许不必要的构造函数 'no-dupe-class-members': 'error', // 不允许在类成员中使用重复名称 'no-duplicate-imports': ['error', { includeExports: true }], // 不允许重复导入 // "import/no-mutable-exports": "error", // 不要导出可变的绑定 // "import/prefer-default-export": "error", // 在只有一个导出的模块里,用 export default 更好 // "import/first": "error", // import 放在其他所有语句之前 'dot-notation': 'error', // 访问属性时使用点符号 'no-restricted-properties': 'error', // 做幂运算时用幂操作符 ** 'one-var': ['off', 'always'], // 强制在函数中单独声明变量 'no-multi-assign': 'error', // 不要使用连续变量分配 'no-plusplus': 'error', // 不要使用一元递增递减运算符(++, --) 'no-unused-vars': 'off', // 不允许有未使用的变量 eqeqeq: ['error', 'always'], // 使用 === 和 !== 而不是 == 和 != 'no-case-declarations': 'error', // 不允许在case/default子句中使用词法声明 'no-nested-ternary': 'error', // 三元表达式不应该嵌套,通常是单行表达式 'no-unneeded-ternary': 'error', // 避免不需要的三元表达式 'no-mixed-operators': 'error', // 不允许不同运算符的混合 'nonblock-statement-body-position': ['error', 'beside'], // 强制单行语句的位置 'brace-style': 'error', // 需要大括号样式 'no-else-return': 'error', // 如果if语句都要用return返回,那后面的else就不用写了。如果if块中包含return,它后面的else if块中也包含了return,这个时候就可以把else if拆开 'spaced-comment': [ 'error', 'always', { line: { markers: ['/'], exceptions: ['-', '+'], }, block: { markers: ['!'], exceptions: ['*'], balanced: true, }, }, ], // "indent": ["error", 2, { "SwitchCase": 1}], // 强制2个空格 'keyword-spacing': ['error', { before: true }], // 在关键字前后强制使用一致的间距 'space-infix-ops': ['error', { int32Hint: false }], // 用空格来隔开运算符 'padded-blocks': ['error', 'never'], // 不要故意留一些没必要的空白行 'array-bracket-spacing': ['error', 'never'], // 方括号里不要加空格 'object-curly-spacing': ['error', 'always'], // 花括号 {} 里加空格 'comma-spacing': ['error', { before: false, after: true }], // , 前避免空格, , 后需要空格 'key-spacing': ['error', { beforeColon: false }], // 在对象的属性中, 键值之间要有空格 'no-trailing-spaces': 'error', // 行末不要空格 'no-multiple-empty-lines': 'error', // 避免出现多个空行。 在文件末尾只允许空一行 'no-new-wrappers': 'error', // 不允许基元包装实例 radix: ['error', 'as-needed'], // 需要基数参数 // "id-length": "error", camelcase: ['error', { properties: 'always' }], // 要求驼峰式命名对象、函数、实例 'new-cap': 'off', // 要求构造函数名称以大写字母开头 'no-underscore-dangle': 'error', // 不要用前置或后置下划线 },
// 可以忽略代码中的 window $这些
globals: {
initGeetest: true,
window: true,
},
};
Stylelint 配置
stylelint-config-standard 是 stylelint 的推荐配置
stylelint-order css 属性排序插件(先写定位,再写盒模型,再写内容区样式,最后写 CSS3 相关属性)
stylelint-config-recess-order stylelint-order 插件的第三方配置
npm i stylelint stylelint-config-standard stylelint-order stylelint-config-recess-order -D
根目录新建一个 .stylelintrc.js 文件、
module.exports = { processors: [], plugins: [], extends: ['stylelint-config-standard', 'stylelint-config-recess-order'], rules: { // 不需要 'space-before-function-paren': 0, // 函数定义时括号前面要不要有空格 'eol-last': 0, // 文件以单一的换行符结束 'no-extra-semi': 0, // 可以多余的冒号 semi: 0, // 语句可以不需要分号结尾 eqeqeq: 0, // 必须使用全等 'one-var': 0, // 连续声明 'no-undef': 0, // 可以 有未定义的变量 // 警告 'no-extra-boolean-cast': 1, // 不必要的bool转换 'no-extra-parens': 1, // 非必要的括号 'no-empty': 1, // 块语句中的内容不能为空 'no-use-before-define': [1, 'nofunc'], // 未定义前不能使用 complexity: [1, 10], // 循环复杂度 'no-unused-vars': 1, // 不能有声明后未被使用的变量或参数 // vue 'flow-vars/define-flow-type': 1, 'flow-vars/use-flow-type': 1, // react 'react/jsx-uses-react': 2, 'react/jsx-uses-vars': 2, // 错误 'comma-dangle': [2, 'never'], // 对象字面量项尾不能有逗号 'no-debugger': 2, // 禁止使用debugger 'no-constant-condition': 2, // 禁止在条件中使用常量表达式 if(true) if(1) 'no-dupe-args': 2, // 函数参数不能重复 'no-dupe-keys': 2, // 在创建对象字面量时不允许键重复 {a:1,a:1} 'no-duplicate-case': 2, // switch中的case标签不能重复 'no-empty-character-class': 2, // 正则表达式中的[]内容不能为空 'no-invalid-regexp': 2, // 禁止无效的正则表达式 'no-func-assign': 2, // 禁止重复的函数声明 'valid-typeof': 2, // 必须使用合法的typeof的值 'no-unreachable': 2, // 不能有无法执行的代码 'no-unexpected-multiline': 2, // 避免多行表达式 'no-sparse-arrays': 2, // 禁止稀疏数组, [1,,2] 'no-shadow-restricted-names': 2, // 严格模式中规定的限制标识符不能作为声明时的变量名使用 'no-cond-assign': 2, // 禁止在条件表达式中使用赋值语句 'no-native-reassign': 2, // 不能重写native对象 // 代码风格 'no-else-return': 1, // 如果if语句里面有return,后面不能跟else语句 'no-multi-spaces': 1, // 不能用多余的空格 'key-spacing': [ 1, { // 对象字面量中冒号的前后空格 beforeColon: false, afterColon: true, }, ], 'block-scoped-var': 2, // 块语句中使用var 'consistent-return': 2, // return 后面是否允许省略 'accessor-pairs': 2, // 在对象中使用getter/setter 'dot-location': [2, 'property'], // 对象访问符的位置,换行的时候在行首还是行尾 'no-lone-blocks': 2, // 禁止不必要的嵌套块 'no-labels': 2, // 禁止标签声明 'no-extend-native': 2, // 禁止扩展native对象 'no-floating-decimal': 2, // 禁止省略浮点数中的0 .5 3. 'no-loop-func': 2, // 禁止在循环中使用函数(如果没有引用外部变量不形成闭包就可以) 'no-new-func': 2, // 禁止使用new Function 'no-self-compare': 2, // 不能比较自身 'no-sequences': 2, // 禁止使用逗号运算符 'no-throw-literal': 2, // 禁止抛出字面量错误 throw "error"; 'no-return-assign': [2, 'always'], // return 语句中不能有赋值表达式 'no-redeclare': [ 2, { // 禁止重复声明变量 builtinGlobals: true, }, ], 'no-unused-expressions': [ 2, { // 禁止无用的表达式 allowShortCircuit: true, allowTernary: true, }, ], 'no-useless-call': 2, // 禁止不必要的call和apply 'no-useless-concat': 2, 'no-void': 2, // 禁用void操作符 'no-with': 2, // 禁用with 'space-infix-ops': 2, // 中缀操作符周围要不要有空格 'valid-jsdoc': [ 2, { // jsdoc规则 requireParamDescription: true, requireReturnDescription: true, }, ], 'no-warning-comments': [ 2, { // 不能有警告备注 terms: ['todo', 'fixme', 'any other term'], location: 'anywhere', }, ], curly: 1, // 必须使用 if(){} 中的{} // common js // 常用规则 // 规则的细节请到ESLint官方网站查看官网 'no-duplicate-imports': 1, 'comma-dangle': ['error', 'never'], //是否允许对象中出现结尾逗号 'no-cond-assign': 2, //条件语句的条件中不允许出现赋值运算符 'no-console': 2, //不允许出现console语句 'no-constant-condition': 2, //条件语句的条件中不允许出现恒定不变的量 'no-control-regex': 2, //正则表达式中不允许出现控制字符 'no-debugger': 2, //不允许出现debugger语句 'no-dupe-args': 2, //函数定义的时候不允许出现重复的参数 'no-dupe-keys': 2, //对象中不允许出现重复的键 'no-duplicate-case': 2, //switch语句中不允许出现重复的case标签 'no-empty': 2, //不允许出现空的代码块 'no-empty-character-class': 2, //正则表达式中不允许出现空的字符组 'no-ex-assign': 2, //在try catch语句中不允许重新分配异常变量 'no-extra-boolean-cast': 2, //不允许出现不必要的布尔值转换 'no-extra-parens': 0, //不允许出现不必要的圆括号 'no-extra-semi': 2, //不允许出现不必要的分号 'no-func-assign': 2, //不允许重新分配函数声明 'no-inner-declarations': ['error', 'functions'], //不允许在嵌套代码块里声明函数 'no-invalid-regexp': 2, //不允许在RegExp构造函数里出现无效的正则表达式 'no-irregular-whitespace': 2, //不允许出现不规则的空格 'no-negated-in-lhs': 2, //不允许在in表达式语句中对最左边的运算数使用取反操作 'no-obj-calls': 2, //不允许把全局对象属性当做函数来调用 'no-regex-spaces': 2, //正则表达式中不允许出现多个连续空格 'quote-props': 2, //对象中的属性名是否需要用引号引起来 'no-sparse-arrays': 2, //数组中不允许出现空位置 'no-unreachable': 2, //在return,throw,continue,break语句后不允许出现不可能到达的语句 'use-isnan': 2, //要求检查NaN的时候使用isNaN() 'valid-jsdoc': [ 'error', { requireReturn: false, requireParamDescription: false, requireReturnDescription: true, }, ], //强制JSDoc注释 'valid-typeof': [ 'error', { requireStringLiterals: true, }, ], //在使用typeof表达式比较的时候强制使用有效的字符串 'block-scoped-var': 2, //将变量声明放在合适的代码块里 complexity: 0, //限制条件语句的复杂度 'consistent-return': 2, //无论有没有返回值都强制要求return语句返回一个值 curly: ['error', 'all'], //强制使用花括号的风格 'default-case': 0, //在switch语句中需要有default语句 'dot-notation': ['error', { allowKeywords: false, allowPattern: '' }], //获取对象属性的时候使用点号 eqeqeq: ['error', 'smart'], //比较的时候使用严格等于 'no-alert': 1, //不允许使用alert,confirm,prompt语句 'no-caller': 2, //不允许使用arguments.callee和arguments.caller属性 'guard-for-in': 0, //监视for in循环,防止出现不可预料的情况 'no-div-regex': 2, //不能使用看起来像除法的正则表达式 'no-else-return': 0, //如果if语句有return,else里的return不用放在else里 'no-labels': [ 'error', { allowLoop: false, allowSwitch: false, }, ], //不允许标签语句 'no-eq-null': 2, //不允许对null用==或者!= 'no-eval': 2, //不允许使用eval() 'no-extend-native': 2, //不允许扩展原生对象 'no-extra-bind': 2, //不允许不必要的函数绑定 'no-fallthrough': 2, //不允许switch按顺序全部执行所有case 'no-floating-decimal': 2, //不允许浮点数缺失数字 'no-implied-eval': 2, //不允许使用隐式eval() 'no-iterator': 2, //不允许使用__iterator__属性 'no-lone-blocks': 2, //不允许不必要的嵌套代码块 'no-loop-func': 2, //不允许在循环语句中进行函数声明 'no-multi-spaces': 2, //不允许出现多余的空格 'no-multi-str': 2, //不允许用\来让字符串换行 'no-global-assign': 2, //不允许重新分配原生对象 'no-new': 2, //不允许new一个实例后不赋值或者不比较 'no-new-func': 2, //不允许使用new Function 'no-new-wrappers': 2, //不允许使用new String,Number和Boolean对象 'no-octal': 2, //不允许使用八进制字面值 'no-octal-escape': 2, //不允许使用八进制转义序列 'no-param-reassign': 0, //不允许重新分配函数参数"no-proto": 2, //不允许使用__proto__属性 'no-redeclare': 2, //不允许变量重复声明 'no-return-assign': 2, //不允许在return语句中使用分配语句 'no-script-url': 2, //不允许使用javascript:void(0) 'no-self-compare': 2, //不允许自己和自己比较 'no-sequences': 2, //不允许使用逗号表达式 'no-throw-literal': 2, //不允许抛出字面量错误 throw "error" 'no-unused-expressions': 2, //不允许无用的表达式 'no-void': 2, //不允许void操作符 'no-warning-comments': [1, { terms: ['todo', 'fixme', 'any other term'] }], //不允许警告备注 'no-with': 2, //不允许使用with语句 radix: 1, //使用parseInt时强制使用基数来指定是十进制还是其他进制 'vars-on-top': 0, //var必须放在作用域顶部 'wrap-iife': [2, 'any'], //立即执行表达式的括号风格 yoda: [2, 'never', { exceptRange: true }], //不允许在if条件中使用yoda条件 strict: [2, 'function'], //使用严格模式 'no-catch-shadow': 2, //不允许try catch语句接受的err变量与外部变量重名"no-delete-var": 2, //不允许使用delete操作符 'no-label-var': 2, //不允许标签和变量同名 'no-shadow': 2, //外部作用域中的变量不能与它所包含的作用域中的变量或参数同名 'no-shadow-restricted-names': 2, //js关键字和保留字不能作为函数名或者变量名 'no-undef': 2, //不允许未声明的变量 'no-undef-init': 2, //不允许初始化变量时给变量赋值undefined 'no-undefined': 2, //不允许把undefined当做标识符使用 'no-unused-vars': [2, { vars: 'all', args: 'after-used' }], //不允许有声明后未使用的变量或者参数 'no-use-before-define': [2, 'nofunc'], //不允许在未定义之前就使用变量"indent": 2, //强制一致的缩进风格 'brace-style': [2, '1tbs', { allowSingleLine: false }], //大括号风格 camelcase: [2, { properties: 'never' }], //强制驼峰命名规则 'comma-style': [2, 'last'], //逗号风格 'consistent-this': [0, 'self'], //当获取当前环境的this是用一样的风格 'eol-last': 2, //文件以换行符结束 'func-names': 0, //函数表达式必须有名字 'func-style': 0, //函数风格,规定只能使用函数声明或者函数表达式 'key-spacing': [2, { beforeColon: false, afterColon: true }], //对象字面量中冒号的前后空格 'max-nested-callbacks': 0, //回调嵌套深度 'new-cap': [2, { newIsCap: true, capIsNew: false }], //构造函数名字首字母要大写 'new-parens': 2, //new时构造函数必须有小括号 'newline-after-var': 0, //变量声明后必须空一行 'no-array-constructor': 2, //不允许使用数组构造器 'no-inline-comments': 0, //不允许行内注释 'no-lonely-if': 0, //不允许else语句内只有if语句 'no-mixed-spaces-and-tabs': [2, 'smart-tabs'], //不允许混用tab和空格 'no-multiple-empty-lines': [2, { max: 2 }], //空行最多不能超过两行 'no-nested-ternary': 2, //不允许使用嵌套的三目运算符 'no-new-object': 2, //禁止使用new Object() 'fun-call-spacing': 2, //函数调用时,函数名与()之间不能有空格 'no-ternary': 0, //不允许使用三目运算符 'no-trailing-spaces': 2, //一行最后不允许有空格 'no-underscore-dangle': 2, //不允许标识符以下划线开头 'no-extra-parens': 0, //不允许出现多余的括号 'one-var': 0, //强制变量声明放在一起 'operator-assignment': 0, //赋值运算符的风格 'padded-blocks': [2, 'never'], //块内行首行尾是否空行 'quote-props': 0, //对象字面量中属性名加引号 quotes: [1, 'single', 'avoid-escape'], //引号风格 semi: [2, 'always'], //强制语句分号结尾 'semi-spacing': [2, { before: false, after: true }], //分后前后空格 'sort-vars': 0, //变量声明时排序 'space-before-blocks': [2, 'always'], //块前的空格 'space-before-function-paren': [2, { anonymous: 'always', named: 'never' }], //函数定义时括号前的空格 'space-infix-ops': [2, { int32Hint: true }], //操作符周围的空格 'keyword-spacing': 2, //关键字前后的空格 'space-unary-ops': [2, { words: true, nonwords: false }], //一元运算符前后不要加空格 'wrap-regex': 2, //正则表达式字面量用括号括起来 'no-var': 0, //使用let和const代替var 'generator-star-spacing': [2, 'both'], //生成器函数前后空格 'max-depth': 0, //嵌套块深度 'max-len': 0, //一行最大长度,单位为字符 'max-params': 0, //函数最多能有多少个参数 'max-statements': 0, //函数内最多有几个声明 'no-bitwise': 0, //不允许使用位运算符 'no-plusplus': 0, //不允许使用++ --运算符}, // 可以自己自定一些规则 }, };
Commitlint 配置
@commitlint/cli 可以检查提交信息
@commitlint/config-conventional 是提交规范的配置包
npm i @commitlint/cli @commitlint/config-conventional -D
根目录下新建commitlint.config.js文件
/* 规范commit日志 https://commitlint.js.org */ const types = [ 'build', // 主要目的是修改项目构建系统(例如glup,webpack,rollup的配置等)的提交 'ci', // 修改项目的持续集成流程(Kenkins、Travis等)的提交 'chore', // 构建过程或辅助工具的变化 'docs', // 文档提交(documents) 'feat', // 新增功能(feature) 'fix', // 修复 bug 'pref', // 性能、体验相关的提交 'refactor', // 代码重构 'revert', // 回滚某个更早的提交 'style', // 不影响程序逻辑的代码修改、主要是样式方面的优化、修改 'test', // 测试相关的开发, ], typeEnum = { rules: { 'type-enum': [2, 'always', types], }, value: () => { return types; }, }; module.exports = { extends: ['@commitlint/config-conventional'], /* Level [0..2]: 0 disables the rule. For 1 it will be considered a warning for 2 an error. https://commitlint.js.org/#/reference-rules */ rules: { 'type-enum': typeEnum.rules['type-enum'], 'subject-full-stop': [0, 'never'], 'subject-case': [0, 'never'], }, };
配置 lint-staged 规则
在 package.json 里 添加
"lint-staged": { "*.{js,vue}": [ "prettier --write", "eslint --fix", ], "*.less": [ "stylelint --fix" ] }
配置 husky 检验钩子
在 package.json 里 添加
"husky": { "hooks": { "pre-commit": "lint-staged", // 可以配置指令 下面 是配置文件 "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" } }
依赖目录
{
"husky": "^4.2.5",
"lint-staged": "^11.0.1",
"eslint": "^6.8.0",
"eslint-plugin-html": "^6.1.0",
"eslint-plugin-vue": "^6.2.2",
"babel-eslint": "^10.1.0",
"stylelint": "^13.13.1",
"stylelint-config-recess-order": "^2.4.0",
"stylelint-config-standard": "^22,
"@commitlint/cli": "^12.1.4",
"@commitlint/config-conventional": "^12.1.4",
}
本文来自博客园,作者:玖捌,转载请注明原文链接:https://www.cnblogs.com/fyh0912/p/16798339.html
浙公网安备 33010602011771号