项目组 eslint 统一配置及疑难解决

背景

项目组前端代码eslint久失维护,大家有的人有代码规范,有的人没有。新来的代码规范也是从老的手里copy一份。每个人eslint插件的版本、配置、代码项均不同。导致改代码的时候,为了避免自动fix带来的大量代码改动,不得不暂时关闭eslint,改完后,无规则校验上库。代码规范缺乏校验,上库代码质量日益下降。

第一步

按照可信认证规则(标准代码规范)配置eslintrc文件,插件的配置自不必说。为了支持js/ts/jsx/tsx ,需要安装eslint的4个插件,配置在plugin中。注意为了支持tsparser需要指定为@typescript-eslint/parser。否则无法校验ts规则。

  • eslint-react
  • eslint-react-hooks
  • eslint-typescript
  • eslint-@typescript-eslint

编写eslint fix脚本,全局fix项目中的代码。共计上库改动600余个文件。

eslintrc.js

module.exports = {
     
    'root':true,
    'env': {
     
        'browser': true,
        'es6': true,
        'node': true
    },
    'globals': {
     
        'Atomics': 'readonly',
        'SharedArrayBuffer': 'readonly'
    },
    "parser": "@typescript-eslint/parser",
    'parserOptions': {
     
        'ecmaFeatures': {
     
            'jsx': true
        },
        'ecmaVersion': 6,
        'sourceType': 'module'
    },
    'plugins': [
        'react',
        "react-hooks",
        "typescript",
        "@typescript-eslint"
    ],
    'settings':{
     
        "react": {
     
            "version": "16.13.0", 
          },
    },
    "overrides": [
        {
     
            "files":["*.tsx","*.jsx"],
            "rules": {
     
                "react/jsx-indent-props": 0, //禁用验证JSX中的props缩进
            }
        }
    ],
  //覆盖规则
    'rules': {
     
        'indent': [//缩进
            'error',
            4
        ],
        'semi': [//语句强制分号结尾
            'error',
            'always'
        ],
        //参数一:0或‘off’ 关闭规则,1或‘warn’  规则等级警告,2或者‘error’  规则等级错误
        //参数二:可以使用默认,也可以根据文档自定义
        'no-unused-vars': 0,//禁止出现未使用过的变量
        'no-console': 1,//建议不使用console
        'no-var': 1,//建议使用let或const替代var
        'object-shorthand': 2,//对象属性、方法简写语法
        'prefer-spread':1,//建议使用扩展运算符...复制数组
        'comma-dangle': ['error', {
     
            'arrays': 'only-multiline',
            'objects': 'only-multiline',
            'imports': 'never',
            'exports': 'never',
            'functions': 'ignore'
        }],//要求使用尾逗号
        'func-style':['error','declaration',{
     "allowArrowFunctions": true}],//要求函数使用声明式取代表达式
        'prefer-rest-params':2,//要求使用rest语法...替代arguments
        'no-param-reassign':1,//函数参数禁止再赋值
        "curly": ["error", "all"],//控制语句使用大括号
        "prefer-destructuring": ["warn", {
     
            "array": true,
            "object": true
            }, {
     
            "enforceForRenamedProperties": false//解构是否应用于重构
        }],//数组解构和对象解构
        "max-len": ["warn", 120, 4],//行的最大长度120 缩进4
        'no-eval':2,//禁止使用eval
        'no-with':2,//禁止使用with
        'brace-style':[2,'1tbs',{
     "allowSingleLine": true}],//花括号风格:左开与语句在同一行,允许花括号左右在同一行
        'no-const-assign':2,//禁止修改const声明变量
        'no-empty':[1,{
     "allowEmptyCatch": true }],//建议不要存在空语句块,允许catch块为空
        'no-cond-assign':[2,"always"],//禁止在 if、for、while 和 do...while 语句中出现模棱两可的赋值操作符
        'no-unreachable':2,//禁止在 return、throw、continue 和 break 语句后出现不可达代码


        "jsx-quotes": [2, "prefer-double"], //强制在JSX属性(jsx-quotes)中一致使用双引号
        "react/jsx-closing-bracket-location": 0, //在JSX中验证右括号位置
        "react/jsx-curly-spacing": [2, {
     "when": "never", "children": true}], //在JSX属性和表达式中加强或禁止大括号内的空格。
        "react/jsx-indent-props": [2, 4], //验证JSX中的props缩进
        "react/jsx-key": 2, //在数组或迭代器中验证JSX具有key属性
        "react/jsx-no-bind": 0, //JSX中不允许使用箭头函数和bind
        "react/jsx-no-duplicate-props": 2, //防止在JSX中重复的props
        "react/jsx-no-undef": 1, //在JSX中禁止未声明的变量
        "react/jsx-pascal-case": 1, //为用户定义的JSX组件强制使用PascalCase
        "react/jsx-uses-vars": 1, //防止在JSX中使用的变量被错误地标记为未使用
        "react/no-danger": 1, //防止使用危险的JSX属性
        "react/no-did-mount-set-state": 0, //防止在componentDidMount中使用setState
        "react/no-did-update-set-state": 1, //防止在componentDidUpdate中使用setState
        "react/no-direct-mutation-state": 2, //防止this.state的直接变异
        "react/no-multi-comp": 1, //防止每个文件有多个组件定义
        "react/no-set-state": 0, //防止使用setState
        "react/no-unknown-property": 2, //防止使用未知的DOM属性
        "react/prefer-es6-class": 2, //为React组件强制执行ES5或ES6类
        "react/prop-types": 0, //防止在React组件定义中丢失props验证
        "react/react-in-jsx-scope": 2, //使用JSX时防止丢失React
        "react/self-closing-comp": 0, //防止没有children的组件的额外结束标签
        "react/sort-comp": 1, //强制组件方法顺序
        "no-extra-boolean-cast": 0, //禁止不必要的bool转换
        "react/no-array-index-key": 0, //防止在数组中遍历中使用数组key做索引
        "react/no-deprecated": 1, //不使用弃用的方法
        "react/jsx-equals-spacing": 2, //在JSX属性中强制或禁止等号周围的空格
        "comma-dangle": 2, // 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号
        "comma-spacing": [2, {
     'before': false, 'after': true}],  // 控制逗号前后的空格
        "no-mixed-spaces-and-tabs": 0, //禁止混用tab和空格
        "prefer-arrow-callback": 0, //比较喜欢箭头回调


        //空格 建议
        "space-before-blocks": [1, "always"],//代码块花括号左{空格
        "space-before-function-paren": [1, "never"],//函数定义时括号前面要有空格
        "space-in-parens": [1, "never"],//小括号里面要有空格
        "space-infix-ops":[1,{
     "int32Hint": true}],//操作符空格 true允许B|0


        //--FIX dyj react-hooks相关
        "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks


        //--FIX dyj 补充可信认证中的规范
        "arrow-body-style":1,  //--规则31 箭头函数的简写
        "eqeqeq":1, //--建议47 判断相等时使用 === 和 !== ,而不是 == 和 !=
        "no-else-return":1, //--规则32 要求使用一致的 return 语句
        "no-useless-return":1,//--规则 66 禁止多余的 return 语句
        "consistent-return":1,
        "prefer-template":1,//--规则36 使用模板字符串(`)实现字符串拼接
        "no-prototype-builtins":1, //--规则 43 禁止在对象实例上直接使用 Object.prototypes 的内置属性
        "dot-notation":1, //--规则 41 使用点号来访问对象的属性,只有属性是动态的时候使用 []
        "guard-for-in":1, //规则 44 需要约束 for-in
        "no-nested-ternary":1, //规则 46 禁止使用嵌套的三元表达式
        "default-case":1, // 规则 47 每个 switch 语句都包含一个 default 语句,即使它不包含任何代码
        "no-case-declarations":1, //--规则 49 case 语句中需要声明词法时, 花括号 {} 不能省略
        "no-duplicate-imports":1, //--规则 52 不要多次 import 同一个模块
        "no-useless-rename":1, //--规则 55 不要从 import 中直接 export
        "no-floating-decimal":1,//--规则 57 禁止省略小数点前后的 0
        "use-isnan":1,//--规则 58 要求调用 isNaN() 检查 NaN
        "no-unsafe-finally":1,//--规则 59 禁止在 finally 语句块中出现控制流语句
        "no-return-await":1,//--规则 60 禁用不必要的 return await
        "no-implicit-coercion":1, //--规则 65 禁止使用较短的符号实现类型转换
        "new-cap":1, //--构造器函数、类采用首字母大写的驼峰命名方法
        "no-shadow":1,//--规则67 块内变量不能与函数内的其他变量同名,块内函数应该使用函数表达式声明
    }

}
 "scripts": {
     
	"eslint": "eslint src scripts config   --ext .jsx --ext .tsx --ext .js --ext ts -o eslint-report.txt -c .eslintrc.js",
    "eslint-fix": "eslint --fix src scripts config  --ext .jsx --ext .tsx --ext .js --ext ts -c .eslintrc.js",
  },

第二步

通过npm run eslint 生成报告,手动修改无法fix的问题,例如重复props、绕过setState直接修改state、或者参数重赋值等问题累计60余处。
项目组 eslint 统一配置及疑难解决_第1张图片

第三步

配置 eslint-vscode插件。统一使用2.1.14版本,使用通用的工作区设定:

{
     
	"eslint.run": "onType",
	"eslint.format.enable":true,
	 "eslint.options": {
     
	     "extensions": [
	         "web.js",
	         "js",
	         "web.ts",
	         "ts",
	         "web.tsx",
	         "tsx",
	         "json",
	         "web.jsx",
	         "jsx",
	         "node"
	     ]
	 },
	 "editor.codeActionsOnSave": {
     
	     "source.fixAll.eslint": true
	 },
	 "editor.suggestSelection": "first"
 }

项目组 eslint 统一配置及疑难解决_第2张图片

第四步

设置webpack编译时校验(仅限开发模式)

rules: [
 // Disable require.ensure as it's not a standard language feature.
        {
      parser: {
      requireEnsure: false } },

        // First, run the linter.
        // It's important to do this before Babel processes the JS.
        isEnvDevelopment ? {
     
            test: /\.(js|mjs|jsx|ts|tsx)$/,
            enforce: 'pre',
            use: [
                {
     
                    options: {
     
                        formatter: require.resolve('react-dev-utils/eslintFormatter'),
                        eslintPath: require.resolve('eslint')
        
                    },
                    loader: require.resolve('eslint-loader')
                }
            ],
            include: paths.appSrc
        } : {
     },
  ]

问题

1、eslint规则冲突 导致无限fix

解决eslint规则冲突的问题。eslint规则冲突会导致不论是eslint-vscode插件还是npm eslint,无限fix代码的过程。例如最常见的,eslint 原始规则 indent,设置代码应该的间隔,极容易与react插件配置的一些规则冲突。这时候,就需要我们对react后缀(jsx、tsx)文件做覆盖规则处理:

//--eslintrc.js
 "overrides": [
        {
     
            "files":["*.tsx","*.jsx"],
            "rules": {
     
                "react/jsx-indent-props": 0, //禁用验证JSX中的props缩进
            }
        }
    ]

2、项目成员明明eslint配置全部一致,实际规则却不一致

这是由于eslint在查找配置文件时,会不断的冒泡向上查找规则直到系统根路径。如果eslintrc.js没有配置root:true。参加这里,则eslint会不断的在电脑中寻找配置文件。部分成员根目录中配置了额外规则,导致覆写的时候出现问题。在eslintrc.js中添加即可

'root':true

五、成效

项目成员使用统一的eslint规范,再也不用害怕ctrl+s改坏原来的代码。且存在代码坏味道的代码会在开发阶段的门禁就被拦截掉,避免引入更大的问题。

项目 Value
自动修复文件数 583
自动修复代码行数 15000
手动修复代码问题(风险问题) 56

你可能感兴趣的:(前端技术,eslint)