最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • ESlint - 盘它

    正文概述 掘金(webArche)   2021-03-20   646

    首先 有一个包叫做eslint, 你所有的一切lint校验都来自于这个包 - 官方文档

    涉及到的前置知识点

    ​ 如下图所示,此时左侧选中的部分(printTips),右侧实时高亮显示

    ESLint的运行原理

    ##Eslint使用

    配置文件

    1. eslint配置文件 .eslintrc.js 举例说明:

      • env - 预先定义那些环境中需要用到的环境变量,可用参数 es6 / node / browser 等

        browser -- 会添加所有浏览器的环境变量,比如window

        node -- 会添加所有nodeJS运行时的环境变量,比如global process等

        es6 -- 启用除了 modules 以外的所有 ECMAScript 6 特性(该选项会自动设置 ecmaVersion 解析器选项为 6)

        commonjs - CommonJS 全局变量和 CommonJS 作用域 (用于 Browserify/WebPack 打包的只在浏览器中运行的代码

        官方文档参考

      • extends - 指定扩展的配置,配置支持递归扩展,支持规则的覆盖和聚合。

        可选属性值:

        1. 指定配置的字符串 - (配置文件的路径、可共享配置的名称(airbnb)、eslint:recommendedeslint:all)

        2. 字符串数组 - 数组每一项的配置继承写在前边的配置 - 例如

          extends: ['eslint:recommended`', 'eslint:all'], // eslint:all的配置继承eslint:recommended的配置

      ​ 官方链接传送门

      • plugins - 这里配置我们需要的lint插件

      • parser - parser选项- 解析器,即告诉eslint你要使用哪个解析器进行解析代码,它支持的选项常用的以下几种:

      Espree - 这个是eslint默认使用的解析器 - 但是一旦我们使用babel的话,我们需要用babel-eslint

    ​ babel-eslint - 这个依赖包允许你使用一些实验性的特性的时候,依然可以使用eslint的语法检查。 主要指es6, es7 等等的.

    ​ @typescript-eslint/parser - typescript语法的解析器,tslint已经弃用,官方不再维护,不必关注。这个主要会支持一些typescript的语法,比如类型断言 const a! : number 或者在使用的时候会有 a as number 这种情况。 ​

    • parserOptions - 在parser配置为babel-eslint的时候,必须配置这个选项,可选值 (。

      ecmaVersion - 默认5, 可指定3、5、6、7、8、9、10,用来指定使用哪一个ECMAScript版本的语法。也可以设置基于年份的JS标准,比如2015(ECMA 6)

      sourceType - 如果你的代码是ECMAScript 模块写的,该字段配置为module,否则为script(默认值)

      ecmaFeatures - 该对象指示你想使用的额外的语言特性

      • rules - 自定义规则配置 --优先级最高,可以覆盖掉我们在extends中配置启用的规则
      • settings - 该字段定义的数据可以在所有的插件中共享。这样每条规则执行的时候都可以访问这里面定义的数据
    module.exports = {
      env: 'es6',
      parser: '@typescript-eslint/parser',
      parserOptions: {
        sourceType: 'module'
      },
      extends: ['eslint:recommended`', 'eslint:all'], // eslint:all的配置继承eslint:recommended的配置
      rules: {
        'no-unused-vars': [
          'error',
          // we are only using this rule to check for unused arguments since TS
          // catches unused variables but not args.
          { varsIgnorePattern: '.*', args: 'after-used', argsIgnorePattern: '^_' }
        ],
        // most of the codebase are expected to be env agnostic
        'no-restricted-globals': ['error', ...DOMGlobals, ...NodeGlobals],
        // since we target ES2015 for baseline support, we need to forbid object
        // rest spread usage (both assign and destructure)
        'no-restricted-syntax': [
          'error',
          'ObjectExpression > SpreadElement',
          'ObjectPattern > RestElement'
        ]
      },
      settings: {
        'import/resolver': { // This config is used by eslint-import-resolver-webpack
          webpack: {
            config: './webpack/webpack-common-config.js'
          }
        },
      },
      overrides: [
        // tests, no restrictions (runs in Node / jest with jsdom)
        {
          files: ['**/__tests__/**', 'test-dts/**'],
          rules: {
            'no-restricted-globals': 'off',
            'no-restricted-syntax': 'off'
          }
        },
        // shared, may be used in any env
        {
          files: ['packages/shared/**'],
          rules: {
            'no-restricted-globals': 'off'
          }
        },
        // Packages targeting DOM
        {
          files: ['packages/{vue,runtime-dom}/**'],
          rules: {
            'no-restricted-globals': ['error', ...NodeGlobals]
          }
        },
        // Packages targeting Node
        {
          files: ['packages/{compiler-sfc,compiler-ssr,server-renderer}/**'],
          rules: {
            'no-restricted-globals': ['error', ...DOMGlobals],
            'no-restricted-syntax': 'off'
          }
        },
        // Private package, browser only + no syntax restrictions
        {
          files: ['packages/template-explorer/**'],
          rules: {
            'no-restricted-globals': ['error', ...NodeGlobals],
            'no-restricted-syntax': 'off'
          }
        }
      ]
    }
    
    

    个人常用配置项扩展说明:

    eslint 配置文件常用的配置选项注意:

    1. parser- 首先需要配置解析器,这个在目前的前端环境下是必须的,如果不配置就是采用默认的javascript解析器 - espree,我们一般使用babel-eslint。 有时候解析选项也是需要进行配置的parserOptions

    2. env - 指定脚本运行的运行时环境,可以同时指定多个,具体见官方文档

    3. extends - 指定我们启用哪一套eslint规则,一般启用标准规则, 这里可以写多个规则启用项目,后边的覆盖前边的,也可引入我们的自定义规则(既如此,我们就可以把我们习惯的规则引入,或者把我们自定义的插件配置在此处)

    4. plugins - 这个地方配置第三方的插件,插件需要安装对应的npm包, 可以写多个,形式为字符串数组, 前缀eslint-plugin-可省略

    5. rules - 此处启用的规则优先级最高,可以配置eslint的自有规则,也可配置从第三方插件中引入的规则(此处需要保证第三方插件的npm包已经安装).

    6. overrides & files - 针对项目中特定的部分文件禁用eslint规则,可进行如下配置:

      overrides: [
       // tests, no restrictions (runs in Node / jest with jsdom)
       {
         files: ['**/__tests__/**', 'test-dts/**'],
         rules: {
           'no-restricted-globals': 'off',
           'no-restricted-syntax': 'off'
         }
       },
       // shared, may be used in any env
       {
         files: ['packages/shared/**'],
         rules: {
           'no-restricted-globals': 'off'
         }
       },
       // Packages targeting DOM
       {
         files: ['packages/{vue,runtime-dom}/**'],
         rules: {
           'no-restricted-globals': ['error', ...NodeGlobals]
         }
       },
       // Packages targeting Node
       {
         files: ['packages/{compiler-sfc,compiler-ssr,server-renderer}/**'],
         rules: {
           'no-restricted-globals': ['error', ...DOMGlobals],
           'no-restricted-syntax': 'off'
         }
       },
       // Private package, browser only + no syntax restrictions
       {
         files: ['packages/template-explorer/**'],
         rules: {
           'no-restricted-globals': ['error', ...NodeGlobals],
           'no-restricted-syntax': 'off'
         }
       }
       ]
      

    编写一个Eslint插件

    ​ 既然要写一个插件,必要明确插件要实现的功能目标,eslint插件可实现一个校验的规则。

    #### 插件要实现的目标
    
    1. 禁止setTimout的第二个参数是数字。
    2. 进阶 - 规则增强 - 项目中禁止出现魔幻变量。

    开发准备工作

    1. eslint官方为了方便开发者开发插件,提供了Yeoman模版(generator-eslint), 它是一个脚手架工具,用于生成包含指定框架结构的工程化目录结构。

      npm install -g yo generator-eslint
      
    2. 创建一个文件夹,用来存放你的项目

      mkdir -p eslint-plugin-demo && cd eslint-plugin-demo
      
    3. 初始化eslint插件的目录结构

      yo eslint:plugin
      

      初始化eslint规则的模版文件

         yo eslint:rule
      

      生成之后的文件目录结构

       ├── README.md
       ├── docs // 使用文档
       │   └── rules // 所有规则的文档
       │       └── settimeout-no-number.md // 具体规则文档
       ├── lib // eslint 规则开发
       │   ├── index.js 引入+导出rules文件夹的规则
       │   └── rules // 此目录下可以构建多个规则
       │       └── settimeout-no-number.js // 规则细节
       ├── package.json
       └── tests // 单元测试
           └── lib
               └── rules
                   └── settimeout-no-number.js // 测试该规则的文件
      

    安装依赖

    npm install
    

    开始开发

    ​ 有2个文件需要我们关注:

    ​ 第一个 lib/rules/settimeout-no-number.js, 这个是规则模板文件,也是我们开发自定义规则的文件: (初始大致这个样子)

    module.exports = {
     meta: {
         docs: {
             description: "setTimeout 第二个参数禁止是数字",
         },
         fixable: null,  // 修复函数
     },
    // rule 核心
     create: function(context) {
        // 公共变量和函数应该在此定义
         return {
             // 返回事件钩子
         };
     }
    };
    

    完整代码:

    /**
     * @fileoverview The second parameter of setTimeout is forbidden to be a number
     * @author Arche
     */
    "use strict";
    
    //------------------------------------------------------------------------------
    // Rule Definition
    //------------------------------------------------------------------------------
    
    module.exports = {
        meta: {
            docs: {
                description: "The second parameter of setTimeout is forbidden to be a number",
                category: "Fill me in",
                recommended: false
            },
            fixable: 'code',  // or "code" or "whitespace" // 是否开启文件修复函数
            schema: [
                // fill in your schema
            ]
        },
    
        create: function(context) {
    
            // variables should be defined here
    
            //----------------------------------------------------------------------
            // Helpers
            //----------------------------------------------------------------------
    
            // any helper functions should go here or else delete this section
    
            //----------------------------------------------------------------------
            // Public
            //----------------------------------------------------------------------
    
            return {
              'CallExpression': (node) => {
                if (node.callee.name !== 'setTimeout') return //检测是否是定时器,不是return
                const parameterTime = node?.arguments[1]; // 获取第二个参数
                if (!parameterTime) return // 如果第二个参数不存在则return
                if(parameterTime.type === 'Literal' && typeof parameterTime.value === 'number') {
                  context.report({
                    node,
                    message: 'The second parameter is forbidden to be a number', // 这个提示信息需要和测试用例中的保持完全一致
                    fix: (fixer) => { // 这个是文件修复函数
                      const numberValue = parameterTime.value;
                      const statementString = `const countNumber = ${numberValue}\n`; // 修复语句
                      return [
                        fixer.replaceTextRange(node.arguments[1], numberValue), // 替换第二个参数位置
                        fixer.insertTextBeforeRange(node.range, statementString) // 在定时器前增加一条语句
                      ]
                    }
                  })
                }
              }
            };
        }
    };
    
    

    第二个 tests/lib/rules/settimeout-no-number.js 这个是测试用例文件。

    /**
    * @fileoverview The seconed parameter of setTimeout is forbidden to be a
    * @author Arche
    */
    "use strict";
    
    //------------------------------------------------------------------------------
    // Requirements
    //------------------------------------------------------------------------------
    
    var rule = require("../../../lib/rules/setTimeout-no-number"),
    
       RuleTester = require("eslint").RuleTester;
    
    
    //------------------------------------------------------------------------------
    // Tests
    //------------------------------------------------------------------------------
    
    var ruleTester = new RuleTester({
     parserOptions: {
       ecmaVersion: 7, // 默认支持语法为es5
     },
    });
    ruleTester.run("setTimeout-no-number", rule, {
    
       valid: [
         {
           code: "let num = 1000; setTimeout(() => { console.log(1) }, num)"
         },
         {
           code: 'setTimeout(()=>{ console.log(11) },someNumber)'
         }
       ],
    
       invalid: [
           {
               code: "setTimeout(() => {}, 1000)",
               errors: [{
                   message: "The second parameter is forbidden to be a number",
                   type: "CallExpression"
               }]
           }
       ]
    });
    
    

    参考资料:

    手摸手教你写个eslint插件以及了解eslint的运行原理

    最全的Eslint配置模板,从此统一团队的编程习惯

    官方文档


    起源地下载网 » ESlint - 盘它

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元