AlloyTeam ESLint 配置指南

FidBinney 7年前
   <p>ESLint 是一个应用广泛的 JavaScript 代码检查工具。本文主要介绍由 AlloyTeam 总结的 ESLint 配置,以及应用 ESLint 配置时的一些经验和工具。</p>    <h2>配置原则</h2>    <p>我们依据以下三条原则,研读了 ESLint 所有的配置项,定制出了心目中「完美」的 <a href="/misc/goto?guid=4959751757347229427" rel="nofollow,noindex">ESLint 配置</a> 。</p>    <ol>     <li>能够帮助发现代码错误的规则,全部开启</li>     <li>配置不应该依赖于某个具体项目,而应尽可能的合理</li>     <li>帮助保持团队的代码风格统一,而不是限制开发体验</li>    </ol>    <h2>配置解读</h2>    <p>我们对每一条配置,都有详尽的注释,这样不仅方便了我们自己查阅某项配置的意义和如此配置的原因,也使大家更容易配置出自己心目中的规则:</p>    <ul>     <li>每一条配置都有注释说明此配置的用途</li>     <li>对于理解困难的配置,都在注释中有举例</li>     <li>对于有争议的配置,都在注释中说明了为什么要这么配置的原因</li>     <li>对于关闭掉的配置,都在注释中有对应的原因说明,以及 @off 的标识</li>     <li>对于能够 autofix 的配置,都在注释中有标注 @autofix</li>    </ul>    <p>详细的配置内容在这里:</p>    <ul>     <li><a href="/misc/goto?guid=4959751757442804563" rel="nofollow,noindex">ESLint 标准规则</a></li>     <li><a href="/misc/goto?guid=4959751757519103546" rel="nofollow,noindex">eslint-plugin-react 规则</a></li>     <li><a href="/misc/goto?guid=4959751757607190979" rel="nofollow,noindex">eslint-plugin-vue 规则</a></li>    </ul>    <p>下面列出一个代码片段供参考:</p>    <pre>  <code class="language-javascript">module.exports = {      parser: 'babel-eslint',      parserOptions: {          ecmaVersion: 2017,          sourceType: 'module',          ecmaFeatures: {              experimentalObjectRestSpread: true,              jsx: true          }      },      env: {          browser: true,          node: true,          commonjs: true,          es6: true      },      // 以当前目录为根目录,不再向上查找 .eslintrc.js      root: true,      rules: {          //          //          // 可能的错误          // 这些规则与 JavaScript 代码中可能的语法错误或逻辑错误有关          //          // 禁止 for 循环出现方向错误的循环,比如 for (i = 0; i < 10; i--)          'for-direction': 'error',          // getter 必须有返回值,并且禁止返回空,比如 return;          'getter-return': [              'error',              {                  allowImplicit: false              }          ],          // 禁止将 await 写在循环里,因为这样就无法同时发送多个异步请求了          // @off 要求太严格了,有时需要在循环中写 await          'no-await-in-loop': 'off',          // 禁止与负零进行比较          'no-compare-neg-zero': 'error',          // 禁止在 if, for, while 里使用赋值语句,除非这个赋值语句被括号包起来了          'no-cond-assign': [              'error',              'except-parens'          ],          // 禁止使用 console          // @off console 的使用很常见          'no-console': 'off',          // 禁止将常量作为 if, for, while 里的测试条件,比如 if (true), for (;;),除非循环内部有 break 语句          'no-constant-condition': [              'error',              {                  checkLoops: false              }          ],          // 禁止在正则表达式中出现 Ctrl 键的 ASCII 表示,即禁止使用 /\x1f/          // 开启此规则,因为字符串中一般不会出现 Ctrl 键,所以一旦出现了,可能是一个代码错误          'no-control-regex': 'error',          // @fixable 禁止使用 debugger          'no-debugger': 'error',          // 禁止在函数参数中出现重复名称的参数          'no-dupe-args': 'error',          // 禁止在对象字面量中出现重复名称的键名          'no-dupe-keys': 'error',      }  };     </code></pre>    <h2>使用方法</h2>    <h3>标准规则</h3>    <p>安装</p>    <pre>  <code class="language-javascript">npm install --save-dev eslint-config-alloy babel-eslint     </code></pre>    <p>配置 .eslintrc.js</p>    <p>在你的项目根目录下创建 .eslintrc.js ,并将以下内容复制到文件中:</p>    <pre>  <code class="language-javascript">module.exports = {      extends: [          'eslint-config-alloy',      ],      globals: {          // 这里填入你的项目需要的全局变量          // 这里值为 false 表示这个全局变量不允许被重新赋值,比如:          //          // jQuery: false,          // $: false      },      rules: {          // 这里填入你的项目需要的个性化配置,比如:          //          // // @fixable 一个缩进必须用两个空格替代          // 'indent': [          //     'error',          //     2,          //     {          //         SwitchCase: 1,          //         flatTernaryExpressions: true          //     }          // ]      }  };     </code></pre>    <h3>React 版</h3>    <p>安装</p>    <pre>  <code class="language-javascript">npm install --save-dev eslint-config-alloy eslint-plugin-react babel-eslint     </code></pre>    <p>配置 .eslintrc.js</p>    <p>在你的项目根目录下创建 .eslintrc.js ,并将以下内容复制到文件中:</p>    <pre>  <code class="language-javascript">module.exports = {      extends: [          'eslint-config-alloy/react',      ],      globals: {          // 这里填入你的项目需要的全局变量          // 这里值为 false 表示这个全局变量不允许被重新赋值,比如:          //          // React: false,          // ReactDOM: false      },      rules: {          // 这里填入你的项目需要的个性化配置,比如:          //          // // @fixable 一个缩进必须用两个空格替代          // 'indent': [          //     'error',          //     2,          //     {          //         SwitchCase: 1,          //         flatTernaryExpressions: true          //     }          // ],          // // @fixable jsx 的 children 缩进必须为两个空格          // 'react/jsx-indent': [          //     'error',          //     2          // ],          // // @fixable jsx 的 props 缩进必须为两个空格          // 'react/jsx-indent-props': [          //     'error',          //     2          // ]      }  };     </code></pre>    <h3>Vue 版</h3>    <p>安装</p>    <pre>  <code class="language-javascript">npm install --save-dev eslint-config-alloy eslint-plugin-vue babel-eslint     </code></pre>    <p>配置 .eslintrc.js</p>    <p>在你的项目根目录下创建 .eslintrc.js ,并将以下内容复制到文件中:</p>    <pre>  <code class="language-javascript">module.exports = {      extends: [          'eslint-config-alloy/vue',      ],      globals: {          // 这里填入你的项目需要的全局变量          // 这里值为 false 表示这个全局变量不允许被重新赋值,比如:          //          // Vue: false      },      rules: {          // 这里填入你的项目需要的个性化配置,比如:          //          // // @fixable 一个缩进必须用两个空格替代          // 'indent': [          //     'error',          //     2,          //     {          //         SwitchCase: 1,          //         flatTernaryExpressions: true          //     }          // ]      }  };     </code></pre>    <h2>代码改造经验</h2>    <p>如果是一个新项目,应用一个比较严格的 ESLint 规则并不是一件难事。</p>    <p>但是如果是一个已经维护多年的老项目,那么突然引入 ESLint 就会有成千上万个错误。这个时候该如何改造呢?</p>    <h3>1. 将所有报错的配置都关闭</h3>    <p>运行 ESLint 之后,会有很多错误,这时候我们可以把他们先暂时关闭掉。</p>    <p>由于项目还在不停地迭代,这样可以保证其他不会报错的规则能够应用到新增的文件上。</p>    <p>这时你的 .eslintrc.js 应该类似与下面的样子:</p>    <pre>  <code class="language-javascript">module.exports = {      extends: [          '@alloyteam/eslint-config-standard',      ],      globals: {          React: false,          jQuery: false,          $: false      },      rules: {          'no-dupe-keys': 'off',          'no-var': 'off',          'complexity': 'off',          'indent': 'off'      }  };     </code></pre>    <p>小技巧:如果报错的规则太多了,可以在运行 ESLint 的时候,加上参数 -f json ,这样的话会以 json 格式输出,然后稍作处理就可以直接得到所有报错的规则了。</p>    <p>注意:一开始不要开启 --fix ,因为修复的太多了,就难以 review 代码了。</p>    <h3>2. 针对每个配置,修复所有报错的文件,优先修复能够 autofix 的配置</h3>    <p>将 .eslintrc.js 中的 rules 删掉一行,然后重新执行 ESLint 检查。</p>    <ul>     <li>如果可以 autofix,则加上 --fix 即可</li>     <li>如果不能 autofix,则需要一个文件一个文件的手动修改</li>    </ul>    <p>建议优先修复能够 autofix 的配置。</p>    <p>在这一步中,我们一次只修复一个 ESLint 配置,这样的好处是 code review 的时候,目的很明确,不会出现问题。</p>    <p>小技巧:如果一个配置不能 autofix,又有很多文件报错,那么可以尝试写一些脚本去处理,利用 ESLint 中的参数 -f json ,可以解析到所有报错的文件和报错的行数。</p>    <p>小技巧:如果写脚本也难以处理,那么可以用编辑器的宏功能快速的执行重复的操作,对于 VSCode,可以使用这个工具: https://github.com/geddski/macros</p>    <p>注意:不要陷于某一个配置的泥潭,优先解决容易修复的问题。</p>    <h3>3. 针对难以修复的配置,将报错的文件忽略掉对应的规则,将来再慢慢修复</h3>    <p>有时一个配置需要理解业务逻辑,读懂上下文,很难去修复。</p>    <p>这个时候,可以在报错的文件头部加上 ESLint 注释,忽略掉对应的规则,将来只要搜索对应的 ESLint 注释就可以一个文件一个文件的修复问题了。</p>    <p>比如 eqeqeq 限制必须使用 === 而不是 == ,代码中使用了 if (result == '2') ,然而我们并不知道 ajax 返回的数据是 number 还是 string。这时候就可以在对应的文件头部加上:</p>    <pre>  <code class="language-javascript">/* eslint eqeqeq:0 */     </code></pre>    <p>这样就可以针对这个文件关闭掉 eqeqeq 这个规则了。</p>    <p>相比于将规则在 .eslintrc.js 中关闭,将 ESLint 注释添加到对应文件的头部的好处是:这些规则虽然对老文件不起效,但是新文件都需要遵守这些规则了。</p>    <p>小技巧:如果需要修改的文件太多了,可以使用我们开发的小工具,批量给文件添加 ESLint 注释: https://github.com/xcatliu/add-eslint-comment</p>    <h2>编辑器插件对 ESLint 的支持</h2>    <p>所有编辑器对 ESLint 的支持都很好,可以参考 <a href="/misc/goto?guid=4959751757691251532" rel="nofollow,noindex">这个页面</a> 安装你的编辑器插件。</p>    <p>以 VSCode 举例,在插件栏中下载安装 ESLint 之后,编写 js 代码时就会有类似下图的提示了:</p>    <p>![ <img src="https://simg.open-open.com/show/fd984910e65c21cdc813aa11233bd25e.png"> ]</p>    <p>注意:如果提示说 eslint 未安装,则需要在命令行安装项目级别的 eslint,或全局安装 eslint:</p>    <pre>  <code class="language-javascript">npm install -g eslint     </code></pre>    <p>VSCode 设置中也可以配置一些 ESLint 选项(以及其他相关选项),比如:</p>    <pre>  <code class="language-javascript">{      // 关闭编辑器自带的 js 检查,建议关闭      "javascript.validate.enable" : false,      // ESLint 在保存时自动修复错误      "eslint.autoFixOnSave": true,      // 输出 ESLint 执行时的 log,ESLint 不生效的时候可以启用看看      // "eslint.trace.server": "messages",      // 配置 ESLint 检查的文件类型,这个配置包括 .js, .jsx, .html, .vue      "eslint.validate": [          "javascript",          "javascriptreact",          "html",          "vue"      ],  }     </code></pre>    <p>快来使用 <a href="/misc/goto?guid=4959751757347229427" rel="nofollow,noindex">AlloyTeam ESLint 规则</a> 吧!</p>    <p> </p>    <p>来自:http://www.alloyteam.com/2017/08/13065/</p>    <p> </p>