前端工程化之代码规范---ESLint + Prettier + husky + lint-staged代码规范全家桶

每个开发者都有自己的习惯,代码的风格也不尽相同,比如缩进的格数,结尾加不加分号,定义函数有没有空格,这些看似好像不起眼的风格,但在多人开发的时候,代码commit提交,可能就会出现一大片冲突,或者过多修改过的情况,对项目管理和维护是极其不友好的,而且在review,阅读项目代码的时候,一个项目中出现几种,甚至10几种的代码风格,我相信没人受得了这事,人都有一种惯性思维,习惯看一种风格,切换到其他风格可能需要适应一下,更别说人手一套风格的项目了,这肯定是不能接受的

代码规范一致性很重要,经历过多人协作项目开发的都知道,代码风格不一样,在commit提交代码的时候,代码可能是一样的,但每行多一个空格,少一个空格,都可能会出现大面积的差异,和冲突,diff比较冲突解决起来就这个环节就能自闭了,这个问题很严重,必须得解决

幸运的是,我们可以通过工具来解决这个看似很棘手的问题:
ESLint + Prettier + husky + lint-staged 这套代码自动化规范工具能很好的解决前端代码规范问题

先来说下每个工具都是干嘛的,最后如何组合在一起在项目中去使用


ESLint: 可参考

ESLint是一个JavaScript代码静态检查工具,可以检查JavaScript的语法错误,提示潜在的bug,可以有效提高代码质量,维持前端团队高度一致的编码风格。ESLint不但提供一些默认的规则,也提供用户自定义规则来约束所写的JavaScript代码。

所有都是可拔插的:

  • 内置规则和自定义规则共用一套规则 API
  • 内置的格式化方法和自定义的格式化方法共用一套格式化 API
  • 额外的规则和格式化方法能够在运行时指定
  • 规则和对应的格式化方法并不强制捆绑使用

每条规则:

  • 各自独立
  • 可以开启或关闭(没有什么可以被认为“太重要所以不能关闭”)
  • 可以将结果设置成警告或者错误

如下等等,很多对应使用场景都有对应的规则。

配置名 作用
array-bracket-newline 在数组开括号后和闭括号前强制换行
array-bracket-spacing 强制数组方括号中使用一致的空格
array-element-newline 强制数组元素间出现换行
block-spacing 禁止或强制在代码块中开括号前和闭括号后有空格
brace-style 强制在代码块中使用一致的大括号风格

更多规则,可参考官方文档
这些规则都是通过一个.eslintrc.js文件和.eslintignore文件去管理的

在这里插入图片描述
.eslintrc.js配置的是代码检查时的代码风格
.eslintignore配置的是对于哪些文件不做检查,和.gitignore的作用一样
.eslintignore示例配置如下:

node_modules/
dist/
.yarn/
src/assets/

.eslintrc.js示例配置如下

module.exports = {
    
    
  "extends": ["airbnb-base"],
  "env": {
    
    
    "es6": true,
    "node": true
  },
  "rules": {
    
    
    "comma-dangle": ["error", "never"], // 要求或禁止末尾逗号:不允许逗号
    "indent": ["error", 2], // JavaScript代码强制使用一致的缩进:2格缩进
    "semi": ["error", "never"], // 不使用分号
    "arrow-parens": ["error", "as-needed"], // 箭头函数的参数可以不使用圆括号
    "linebreak-style": "off", // 取消换行符\n或\r\n的验证
    "object-curly-newline": ["error", {
    
     "consistent": true }], // 花括号内的换行符不一定要格式一致
    "function-paren-newline": "off", // 不验证函数括号内的换行
    "import/extensions": "off", // 取消对文件扩展名的验证
    "no-param-reassign": "off", // 允许对函数参数进行再赋值
    "no-underscore-dangle": "off", // 允许在标识符中使用下划线
    "no-use-before-define": "off", // 允许变量和函数在定义前使用
    "no-unused-expressions": "off", // 允许使用未使用过的表达式,以此来支持a && a()的代码形式
    "no-console": "off", // 启用console控制台
    "consistent-return": "off", // 关闭函数中return的检测
    "no-shadow": "off", // 可以使用同名变量,
    "newline-per-chained-call": "off", //取消方法链调用中的换行符的检测
    "import/newline-after-import": "off"
  }
}

Prettier

Prettier是很火的一个代码美化工具,其中文意思是“漂亮的、机灵的”,它能够解析代码,使用你自己设定的规则来对代码的风格进行自动格式化处理,例如 缩进使用4个空格。

他的整个圈子很强大,有基于各种编辑器的插件(vs code,atom),有脚本类的,有插件类的(eslint的插件eslint-plugin-prettier)

Prettier 是一个前端的代码格式化工具,支持列表如下:

  • JavaScript,包括 ES2017
  • JSX
  • Flow
  • TypeScript
  • CSS, LESS, and SCSS
  • JSON
  • GraphQL

简而言之,这个工具能够使输出代码保持风格一致。

和eslint的关系: eslint能检查出代码的错误,风格不合规则的问题,然后给我们报错,告诉我们在哪里错了,需要我们手动一行一行去改,而Prettier能帮我们去格式化不规范代码,变成规范的,不再需要自己手动去改了,所以在实际项目中eslint和Prettier往往是配合使用的,eslint检查出错误,Prettier格式化不规范代码,这也就需要eslint的检查规则和Prettier的格式化规则需要保持一致

配合使用方式:把Prettier当作eslint的插件去使用
安装:

npm  i -D prettier eslint-plugin-prettier

在eslint的配置文件中添加配置
.eslintrc 或者 .eslintrc.json 或者 .eslintrc.js文件中

{
    
    
  "plugins": ["prettier"],
  "rules": {
    
    
    "prettier/prettier": "error"
  }
}

Husky:可参考

如同其他许多的版本控制系统一样,Git 也具有在特定事件发生之前或之后执行特定脚本代码功能(从概念上类比,就与监听事件、触发器之类的东西类似)。Git Hooks 就是那些在Git执行特定事件(如commit、push、receive等)后触发运行的脚本。

简单的说就是husky这个工具能在一些git的命令上埋下钩子,当我们使用这些命令的时候就会触发之前埋下的脚本,比如常用的pre-commitcommit-msg钩子,能在我们git commit之前调用一下,和提交commit message时再调用一下

场景: 可用于commit提交代码时,检查代码规范和格式化,也可用于检查commit message是否符合message规范


lint-staged

解决的痛点: 每次修改一个文件就给所有文件执行一次lint检查

在代码提交之前,进行代码规则检查能够确保进入git库的代码都是符合代码规则的。但是整个项目上运行lint速度会很慢,lint-staged能够让lint只检测暂存区的文件,所以速度很快。

npm i husky lint-staged -D
在这里插入代码片{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.js": "eslint --fix"
  }
}

原理: git commit时触发pre-commit钩子,运行lint-staged命令,对*.js执行eslint命令。eslint要提前配置好。

npm链接



在项目中的实际组合应用:

目标: 保证项目中的每个开发者,推送到远程仓库时,代码的风格是一致的

思路:

通过lint工具检查代码规范,通过Prettier工具格式化不规范的代码
我们可以在 package.json中设置配置lint命令,来帮助开发者开发完后通过npm run lint 命令检查代码规范,同时配置lint:fix命令,在检查完代码后,不规范的代码通过Prettier格式化
但开发者可能没有代码写完后npm run lint 或者 npm run lint:fix 的习惯怎么办,那就需要通过husky埋下pre-commit脚本,commit之前自动调用npm run lint:fix检查并且格式化代码

配置过程:

.eslintrc.js的配置如下:

module.exports = {
    
    
  env: {
    
    
    browser: true,
    webextensions: true,
    jquery: true
  },
  plugins: ['prettier'],
  extends: [
    'standard',  //使用standard做代码规范
    'plugin:prettier/recommended',
    'prettier/standard',
  ],
  rules: {
    
    
    'prettier/prettier': [
      'error',
      {
    
    
        endOfLine: 'auto'
      }
    ],
    // 继承于standard规则,还包含了import,node,promise,具体规则请看 https://standardjs.com/rules-zhcn.html#javascript-standard-style
    'no-useless-escape': 'off', // 禁用不必要的转义,但由于`\$\{${key}\}` 这样的他识别错误,所以关掉它
    'prefer-promise-reject-errors': 'off', // 可以使用非error对象作为promise reject的原因 有时直接 reject 一个字符串还是比较方便的
    'no-mixed-operators': 'warn', // 混合使用不同的操作符最好用括号括起来明确意图  例如 a && b || c 这样写其实虽然挺直接的,但最好写成 (a && b) || c ,因为standard里是错误,此处改为警告就行
    'no-prototype-builtins': 'warn', // 禁止直接使用 Object.prototypes 的内置属性,建议使用 Object.prototype.hasOwnProperty.call(foo, "bar") 这种方式
    'max-depth': ['error', 5], // 函数嵌套过深,提醒重构
    'max-params': ['error', 7], // 函数参数过多, 注意可以使用对象传参,这里应该调整为5好一点,不过考虑项目有历史代码,先调整为7
    'max-nested-callbacks': ['error', 3], // 最大回调深度 为3层
    'prefer-rest-params': 'warn', // 建议使用解构 ...args 来代替 arguments , arguments 没有 Array.prototype 方法,所以有点不方便
    'no-var': 'error', // 禁止使用 var,必须用 let 或 const
    'for-direction': 'error', // 如果一个 for 循环的停止条件永远无法到达,比如,计数器在错误的方向上移动,将陷入无限循环。
    'getter-return': 'error', // 每个 getter 都期望有返回值
    complexity: ['warn', 5], // 所有代码的独立现行路径条数 例如多个 if else
    'no-empty': 'error', // 禁止空块语句
    'no-inner-declarations': 'error', // 禁止在嵌套的语句块中出现function 声明
    'default-case': 'error', // 要求 Switch 语句中有 Default 分支,如果的确没有 可在最后注释 // No Default
    'guard-for-in': 'warn', // 在使用 for in 遍历对象时,会把从原型链继承来的属性也包括进来,最好增加if判断,比如foo.hasOwnProperty(key),不过注意不要违反 no-prototype-builtins
    'max-classes-per-file': ['warn', 1], // 每个文件中建议只包含1个类 单一责任原则
    'no-alert': 'error', // alert、confirm 和 prompt 被广泛认为是突兀的 UI 元素,应该被一个更合适的自定义的 UI 界面代替。
    'no-empty-function': 'error', // 禁止出现空函数,尤其是箭头函数的空语句块,可以在空函数里写一条注释
    'node/handle-callback-err': 'warn' // 当你使用回调模式时,遇到error最好处理
  }
}

prettier.config.js配置如下: 格式化的风格,和eslint的风格保持一致

module.exports = {
    
    
  printWidth: 120, // 每行代码最大长度
  tabWidth: 2, // 一个tab代表几个空格数,默认为80
  useTabs: false, // 是否使用tab进行缩进,默认为false,表示用空格进行缩减
  semi: false, // 声明后带分号
  singleQuote: true, // 使用单引号
  jsxSingleQuote: true, // 使用单引号
  jsxBracketSameLine: true, // 启用jsx语法,> 放在末尾
  trailingComma: 'none',
  bracketSpacing: true // 对象,数组加空格
}

package.json文件如下:

{
    
    
  "name": "xxxx",
  "version": "1.0.0",
  "description": "xxxx",
  "private": false,
  "main": "src/index.js",
  "repository": "xxxxx",
  "author": "xxxx",
  "license": "None",
  "engines": {
    
    
    "node": ">=10",
    "yarn": ">= 1.0.0"
  },
  "scripts": {
    
    
  	"lint": "eslint .",
    "lint:fix": "eslint . --fix"
  },
  "dependencies": {
    
    },
  "devDependencies": {
    
    
    "autoprefixer": "^9.7.4",
    "husky": "^4.3.0",
    "lint-staged": "^10.5.0",
    "prettier": "^2.1.2",
    "eslint": "^7.11.0",
    //通过使用eslint-config-prettier配置:
    //能够关闭一些不必要的或者是与prettier冲突的lint选项。这样我们就不会看到一些error同时出现两次
    "eslint-config-prettier": "^6.15.0",
    "eslint-config-standard": "^15.0.0",
    "eslint-plugin-import": "^2.22.1",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-prettier": "^3.1.4",
    "eslint-plugin-promise": "^4.2.1",
    "eslint-plugin-standard": "^4.0.2",
    "eslint-plugin-vue": "^7.1.0",
  },
  "peerDependencies": {
    
    },
  "husky": {
    
    
    "hooks": {
    
    
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    
    
    "*.{ts,vue,js}": "eslint --fix"
  }
}

配置完后,当我们执行npm run lint 或者 npm run lint:fix后,工具会自动检查或修复代码
在这里插入图片描述
或者我们直接git add .git commit 提交时,也会触发husky埋下的钩子,调用lint去检查代码
在这里插入图片描述
因为我在代码中加了个debuggereslint --fix是做不到自动修复,他只会针对格式修复,对于console.log,和一些debugger测试的代码,还是需要自己手动删除的

这样我们就能保证推送到远程仓库中的代码风格都是一致的

值得一提的就是,代码规范和commit规范,在项目中往往都是同时使用的,我个人认为他们都是项目管理和项目维护的第一道防线,极其重要

猜你喜欢

转载自blog.csdn.net/fesfsefgs/article/details/109441255