前端代码乱糟糟?是时候引入代码质量检查工具了

Posted 前端儿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端代码乱糟糟?是时候引入代码质量检查工具了相关的知识,希望对你有一定的参考价值。

为了统一团队的代码规范,除了一纸规范说明之外,还需要引入工具进行限制。虽说工具并不能完全实现规范中的规则,但至少能够在一定程度上缓解代码不统一的局面。

相对于后端,前端代码规范的质量检查涉及到html, CSS,javascript ,如今还涉及到SCSS,ES5,JSX,  React,Vue,Angular等,更是复杂。

本文提供了在检查工具方面的规则制定,在编辑器IDE中进行配置,在webpack中进行打包。让开发小伙伴有所参考

相关规则可以在 webpack4项目demo 中看到,里头放了相关的规则链接注释,欢迎围观~

 

1. 工具选取

笔者对常见的代码检查工具做了一番调研,结合规则支持度,配置方式,在编辑器Sublime于Webstrom这只IDE上的支持度,在webpack打包的支持,最终确立了使用如下方案

HTML / tpl:  HTMLHint

CSS / SCSS: StyleLint

JS / JSX: ESLint

 

对比参考: JavaScript 代码静态质量检查   CSS 代码静态质量检查   HTML代码风格检查工具对比

 

尽管如此,这三个插件也并不完美,有太多太多的坑踩遍了,如果你有更合适的套件,欢迎建议~

 

2. 规则制定

选取了工具之后,就需要确立相应的规则。

规则非常多,对我们这种没经验的小白是不可能一条一条自主去选取的,所以需要依据某些参考。但也只能是参考,我们需要把这些通用的设置,结合到我们实际项目中,并一条条去了解规则,最终选出并摘录进我们的规则集中。

ESLint规则

// 自定义的规则
   rules: {
       // 必须使用 === 或 !==,禁止使用 == 或 !=,与 null 比较时除外
       // @warn 在异步接口返回时不确定参数是数值还是字符串,有时可利用这个类型转换
       'eqeqeq': 'warn',
       // 禁止在 if 代码块内出现函数声明
       // @off 在for循环中会经常使用定义var  for(var i = 0; i < 10; ++i)
       'no-inner-declarations': 'off',
       // switch 的 case 内有变量定义的时候,必须使用大括号将 case 内变成一个代码块
       // @off 太严格
       'no-case-declarations': 'off',
       // 禁止使用 !! ~ 等难以理解的运算符
       // @off 有些时候会用到 if (!!abc)   '' + 100   +new Date() 等
       'no-implicit-coercion': 'off',
       // 禁止在全局作用域下定义变量或申明函数
       // @off 太严格
       'no-implicit-globals': 'off',
       // 禁止使用没必要的 {} 作为代码块
       // @off 有时候需要用代码块做逻辑区分
       'no-lone-blocks': 'off',
       // 禁止出现 location.href = 'javascript:void(0)';
       // @off 有时候需要用便捷的 javascript:;
       'no-script-url': 'off',
       // 对象字面量只有一行时,大括号内的首尾必须有空格
       // @off 没有必要限制
       'object-curly-spacing': 'off',
       // 禁止对函数的参数重新赋值
       // @warn 警示即可
       'no-param-reassign': 'warn',
       // 文件最后一行必须有一个空行
       // @error 应该在文件末尾保持一个换行
       'eol-last': 'error',
       // 代码块嵌套的深度禁止超过 10 层
       // @warn 有些特殊情况会出现  警示即可
       'max-depth': [
           'warn',
       ],
       // 禁止函数的循环复杂度超过 100
       // @error 最大值可以宽松点
       'complexity': [
           'error',
           {
               max: 100
           }
       ],
       // 定义过的变量必须使用
       // @warn 多文件互相引用时 偶尔会出现无引用的情况
       'no-unused-vars': [
           'warn',
           {
               vars: 'all',
               args: 'none',
               caughtErrors: 'none',
               ignoreRestSiblings: true
           }
       ],
       // 在ES5中需使用var
       // @off 没有必要限制
       'no-var': 'off',
       // 禁止使用未定义的变量  建议将相关变量在上方 globals 配置项中配置
       // @warn 警示即可
       'no-undef': 'warn',
       // 函数的参数禁止超过10个
       // @warn 警示即可
       'max-params': ['warn', 10],
       // 回调函数嵌套禁止超过 5 层
       // @warn 警示即可
       'max-nested-callbacks': ['warn', 5],
       // 循环内的函数中不能出现循环体条件语句中定义的变量
       // @warn 警示即可
       'no-loop-func': 'warn',
       // Promise 的 reject 中必须传入 Error 对象
       // @off 不需要限制
       'prefer-promise-reject-errors': 'off',
       // 变量声明时尽量使用一个var声明连续的多个
       // @warn 警示即可
       'one-var': [
           'error',
           'consecutive'
       ],
       // 变量申明必须每行一个
       // @error 赋值时保证处于一行即可
       'one-var-declaration-per-line': [
           'error',
           'initializations'
       ],

       // 禁止使用已废弃的 api
       // @off 不需要限制
       'react/no-deprecated': 'off',
       // 禁止使用字符串 ref
       // @warn 警告即可
       'react/no-string-refs': 'warn',
       // 必须使用 Class 的形式创建组件
       // @warn 警告即可
       'react/prefer-es6-class': [
           'warn',
           'always'
       ],
       // 禁止在 componentDidUpdate 里面使用 setState
       // @warn 警告即可
       'react/no-did-update-set-state': 'warn',
       // 组件内方法必须按照一定规则排序
       // @off 不需要限制
       'react/sort-comp': 'off',

       // jsx 的 props 缩进必须为四个空格
       // @off 不需要限制
       // 'react/jsx-indent-props': 'off',
   }


StyleLint规则

ESLint规则也很多,以 stylelint-config-standard 为基础,加入自定义

rules: {
       // 颜色值避免直接使用颜色名
       'color-named': [
           'never', {
               ignore: ['inside-function']
           }
       ],
       // 使用数字或命名的 (可能的情况下) font-weight 值
       'font-weight-notation': 'numeric',
       // 在函数的逗号之后要求有一个换行符或禁止有空白
       'function-comma-newline-after': null,
       // 在函数的括号内要求有一个换行符或禁止有空白
       'function-parentheses-newline-inside': null,
       // url使用引号
       'function-url-quotes': 'always',
       // 禁止小于 1 的小数的前导 0
       'number-leading-zero': 'never',
       // 字符串使用双引号
       'string-quotes': 'double',
       // 要求选择器列表的逗号之前有一个换行符
       'selector-list-comma-newline-before': 'never-multi-line',
       // 在媒体查询的逗号之前禁止有一换行
       'media-query-list-comma-newline-before': 'never-multi-line',
       // 缩进
       'indentation': 4,
       // 禁止低优先级的选择器出现在高优先级的选择器之后
       'no-descending-specificity': null,
       // 禁止空源
       'no-empty-source': null,
       // 禁止缺少文件末尾的换行符
       'no-missing-end-of-source-newline': null
   }

HtmlHint规则

HtmlHint的规则比较少,可以直接自定义

要注意的是它并不支持JS语法,需要使用JSON格式(在webpack中会强制按这个语法parse)

{
   "_comment": [
       "自定义的HTMLHint配置项",
       "规则中文 @see https://segmentfault.com/a/1190000013276858",
       "规则英文 @see https://github.com/yaniswang/HTMLHint/wiki/Rules",

       "使用注释自定义规则 @see https://github.com/yaniswang/HTMLHint/wiki/Usage#cli"
   ],

   "_comment": "标签名必须小写",
   "tagname-lowercase": true,

   "_comment": "属性名必须小写",
   "attr-lowercase": false,

   "_comment": "属性值必须放在双引号中",
   "attr-value-double-quotes": true,

   "_comment": "属性值一定不可为空",
   "attr-value-not-empty": false,

   "_comment": "属性值一定不可重复",
   "attr-no-duplication": true,

   "_comment": "Doctype必须是 HTML 文档的第一行",
   "doctype-first": false,

   "_comment": "标签必须成对",
   "tag-pair": true,

   "_comment": "标签必须自封闭",
   "tag-self-close": false,

   "_comment": "特殊字符必须转义",
   "spec-char-escape": false,

   "_comment": "ID 属性必须唯一",
   "id-unique": true,

   "_comment": "src 属性一定不可为空",
   "src-not-empty": true,

   "_comment": "title 属性必须出现在标签中",
   "title-require": false,

   "_comment": "img 标签必须包含 alt 属性",
   "alt-require": true,

   "_comment": "Doctype 必须是 HTML5",
   "doctype-html5": true,

   "_comment": "ID 和 Class 的命名规则必须统一",
   "id-class-value": false,

   "_comment": "不该使用样式标签",
   "style-disabled": false,

   "_comment": "不该使用行内样式",
   "inline-style-disabled": false,

   "_comment": "不该使用行内脚本",
   "inline-script-disabled": false,

   "_comment": "空格和制表符一定不可混合在行前",
   "space-tab-mixed-disabled": "space4",

   "_comment": "ID 和 Class 一定不可使用广告关键词",
   "id-class-ad-disabled": false,

   "_comment": "href 必须是绝对路径或者相对路径",
   "href-abs-or-rel": false,

   "_comment": "属性值一定不可使用不安全字符",
   "attr-unsafe-chars": true,

   "_comment": "script 标签不该使用在头部",
   "head-script-disabled": false
}

对于页面中嵌入的CSS与JS,也需要进行检查。

在ESlint中提供了 eslint-plugin-html 插件,然而对<style> 与 <script> 造成的缩进处理不当(配置失效的样子),这个是比较难搞的

// 检查html文件(或tpl文件)中的JS
   plugins: [
       'html'
   ],
   settings: {
       'html/html-extensions': ['.html', '.tpl'],
       // 'html/indent': '+4'
   },

在StyleLint中提供了 stylelint-processor-arbitrary-tags 插件,不过新版似乎内置了支持。然而也并算完美,至少能用就行

 

在Sublime,Webstorm或其他编辑器IDE中使用这些工具的前提:

安装NodeJS,然后使用NPM在全局安装以下依赖包

npm i -g eslint babel-eslint eslint-config-alloy eslint-plugin-html eslint-plugin-react stylelint stylelint-config-standard htmlhint

在项目根目录下添加三个工具对应的文件 (这三个文件即为对应的检查规则集),以便代码编辑器在任何地方都能找到配置文件,如

ESLint 和 StyleLint 工具提供了自动修复功能,可以修复简单的错误如少了分号,多了空格,缩进不正确等

但要注意的是,自动修复某些时候可能会使代码发生逻辑或语法错误,需谨慎使用(自动修复后一定一定一定记得比对代码,确保无误)

 

3. 在Sublime中的配置

sublime安装对应的linter工具,以SublimeLinter工具为基础进行配置

Ctrl+Shift+P 调出安装插件层,输入关键字 sublimelinter 进行搜索安装

前端代码乱糟糟?是时候引入代码质量检查工具了

再安装相应的工具插件,SublimeLinter-eslint , SublimeLinter-stylelint, SublimeLinter-contrib-htmlhint

前端代码乱糟糟?是时候引入代码质量检查工具了

安装 ESLint-Formatter 以支持自动修复检查的错误

前端代码乱糟糟?是时候引入代码质量检查工具了

新增一个构建任务,可命名为,StyleLint-Fix.sublime-build 以支持自动修复检查的错误

前端代码乱糟糟?是时候引入代码质量检查工具了

在其中填入以下内容,保存在相应的位置即可

{
   "shell_cmd": "stylelint $folder/node_modules/.bin/eslint --fix $file"
}

接下来就是配置 SublimeLinter

前端代码乱糟糟?是时候引入代码质量检查工具了

打开插件配置,在User部分填入以下内容并保存即可

stylelint配置中的executable全局路径需要设置好

前端代码乱糟糟?是时候引入代码质量检查工具了

// SublimeLinter Settings - User
{
   "debug": true,
   // "delay": 0.2,
   "lint_mode": "manual",
   // "syntax_map": {
   //     "html (django)": "html",
   //     "html (rails)": "html",
   //     "html 5": "html",
   //     "css": "css",
   //     "javascript (babel)": "javascript",
   //     "magicpython": "python",
   //     "php": "html",
   //     "python django": "python",
   //     "pythonimproved": "python"
   // },
   "styles": [
       {
           "scope": "region.yellowish markup.warning.sublime_linter",
           "types": ["warning"]
       },
       {
           "scope": "region.redish markup.error.sublime_linter",
           "types": ["error"]
       },
       {
           "priority": 1,
           "icon": "dot",
           "mark_style": "outline"
       }
   ],
   "linters": {
       "eslint": {
           // 让eslint能够识别html页面中嵌入的JS
           "selector": "source.js | text.html.basic"
       },
       // 下面三个sublimelinter默认都支持,为防止检查干扰,需要禁用它们
       "scsslint": {
           "disable": true
       },
       "csslint": {
           // "disable": true
       },
       "htmllint": {
           "disable": true
       },
       "stylelint": {
           // 似乎Sublime的stylelint需要手动设置到全局路径
           // "executable": "C:\\Users\\e470\\AppData\\Roaming\\npm\\stylelint.cmd"
           "executable": "/usr/local/bin/stylelint"
       }
   }
}

可以看到,在sublimelinter的配置中是以手动(manual)模式进行调用检查的,可以防止某些文件代码量太大,频繁检查消耗性能

需要检查的时候,在当前文件打开命令即可,或者使用对应快捷键(如果看不到命令,就采用重启大法吧)

以下命令关键字都是在以 Ctrl+Shift+P打开命令层的前提下进行的

前端代码乱糟糟?是时候引入代码质量检查工具了

Lint This View ,执行检查

SublimeLinter还支持检查HTML或tpl文件里嵌入的JS和CSS, 但Webstorm不行唷~~

前端代码乱糟糟?是时候引入代码质量检查工具了

Show All Errors,在底部显示错误列表

前端代码乱糟糟?是时候引入代码质量检查工具了

使用 ESlint-formatter进行自动修复JS

前端代码乱糟糟?是时候引入代码质量检查工具了

使用 StyleLint-Fix 进行自动修复CSS

这个需要调出构建任务列表层,或者使用快捷键 Ctrl+Shift+B,选择我们的fix任务执行即可

前端代码乱糟糟?是时候引入代码质量检查工具了

HTMLHint的不提供自动修复功能

 

 4. 在WebStorm中的配置

打开设置

前端代码乱糟糟?是时候引入代码质量检查工具了

启用内置的ESLint检查

前端代码乱糟糟?是时候引入代码质量检查工具了

启用内置的StyleLint检查

前端代码乱糟糟?是时候引入代码质量检查工具了

前端代码乱糟糟?是时候引入代码质量检查工具了

前端代码乱糟糟?是时候引入代码质量检查工具了

安装之后,可能需要重启,在列表中可以看到插件配置入口

 前端代码乱糟糟?是时候引入代码质量检查工具了

因此插件比较特殊,在windows下,bin中请使用 node执行程序的绝对路径 全局 htmlhint的绝对路径

其他环境下就慢慢试吧..

bin:  D:\Program Files\nodejs\node.exe C:\Users\e470\AppData\Roaming\npm\node_modules\htmlhint\bin\htmlhint
path: .htmlhintrc

前端代码乱糟糟?是时候引入代码质量检查工具了

 内置的ESLint与StyleLint不支持自动修复功能,所以我们需要手动创建 File Watcher

前端代码乱糟糟?是时候引入代码质量检查工具了

前端代码乱糟糟?是时候引入代码质量检查工具了

前端代码乱糟糟?是时候引入代码质量检查工具了

配置成手动执行可能会更好些

需要执行的时候,执行即可

 前端代码乱糟糟?是时候引入代码质量检查工具了

 

5. 在webpack中的配置

参考我的webpack项目配置DEMO, 在 webpack.config.js 中传入相应的参数

前端代码乱糟糟?是时候引入代码质量检查工具了

正式使用时autoFix会按需设置,建议修复。如果选择修复,webpack将按模块的设置进行批量修复,可能会有大量文件被修改,所以需要做好代码比对工作

另外,开启自动修复可能会导致webpack编译无限循环的问题,对于这个我们可以引入一个新的插件 time-fix-plugin ,直接调用即可 

new TimeFixPlugin()

前端代码乱糟糟?是时候引入代码质量检查工具了

 

在使用 htmlhint-loader的时候,webpack默认无法识别html资源,在以往我们可以直接使用 htmlWebpackPlugin来识别,因为它内置支持了ejs-loader

但现在这个代码检查插入之后,我们就需要手动设置好html语法的loader。

不能使用 html-loader  ,使用之后会导致无法识别我们的ejs语法,导致htmlWebpackPlugin的资源插入失效

前端代码乱糟糟?是时候引入代码质量检查工具了

解决办法也很简单,使用 ejs-loader 即可,见下方配置

 

另外,在生产模式 npm run build:prod的时候,提供了将检查结果输出到文件的功能(css的不支持),见 lint目录

虽然有点错乱,也够搜索存档用了

 

而具体在webpack的核心配置文件里面,配置也是挺简单的,虽然也有蛮多不如意

首先相关的npm包需要安装好,使用  htmlhint-loader   eslint-loader  stylelint-webpack-plugin

配置核心部分

new HappyPack({
           id: 'js',
           use: configs.lint.js.open ? [{
               loader: 'babel-loader',
               options: {
                   // cacheDirectory: true
               }
           }, {
               enforce: 'pre',
               exclude: /node_modules/,
               loader: 'eslint-loader',
               options: {
                   fix: configs.lint.js.autoFix,
                   cache: true,
                   emitWarning: !configs.lint.js.emitAsError,
                   failOnError: configs.lint.js.failOnError,
                   formatter: require('eslint-friendly-formatter'),
                   outputReport: {
                       filePath: cwdRalativeOutputPath + '/lint/js/[name].xml',
                       formatter: require('eslint-friendly-formatter')
                   }
               }
           }] : [{
               loader: 'babel-loader',
               options: {
                   // cacheDirectory: true
               }
           }]
       }),
       new HappyPack({
           id: 'html',
           use: configs.lint.html.open ? [{
               loader: 'ejs-loader',
               options: {

               }
           }, {
               loader: 'htmlhint-loader',
               enforce: 'pre',
               exclude: /node_modules/,
               options: {
                   configFile: configs.lint.html.configFile,
                   failOnError: configs.lint.html.failOnError,
                   outputReport: {
                       filePath: cwdRalativeOutputPath + '/lint/html/[name].xml'
                   }
               }
           }] : [{
               loader: 'ejs-loader',
               options: {

               }
           }]
       }),






// stylelint检查
if (configs.lint.css.open) {
   commonConfig.plugins.push(new StyleLintPlugin({
       fix: configs.lint.css.autoFix,
       emitErrors: configs.lint.css.emitAsError,
       failOnError: configs.lint.css.failOnError,
       formatter: require('stylelint-formatter-pretty')
   }));
}

 


以上是关于前端代码乱糟糟?是时候引入代码质量检查工具了的主要内容,如果未能解决你的问题,请参考以下文章

如何在Vite项目中使用Lint保证代码质量

pre-commit钩子,代码质量检查

JS代码检查工具ESLint

编写高质量代码改善C#程序的157个建议——建议155:随生产代码一起提交单元测试代码

SonarScanner有效检查代码质量

用于检查和改进代码的PHP代码质量工具