前言
应该有很多同学在配置eslint文件
的时候,会有这样的疑问,为什么每种校验模块包要分成 config/plugin
两个版本,并且有时候在plugins
引入了插件,还可以再以extends方式去使用插件,既然插件这么全能,为何要有 eslint-config-*
呢?
探索
eslint-config-* 的配置形式
以 eslint-config-airbnb 为参考
module.exports = {
extends: [
'eslint-config-airbnb-base',
'./rules/react',
'./rules/react-a11y',
].map(require.resolve),
rules: {}
};
你会发现就是一个简单的.eslintrc
对象,再往它 —> 继承的文件
里去看
以 ./rules/react 为参考
module.exports = {
plugins: [
'react',
],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
rules: {...无数规则声明s}
}
是不是很神奇,继承链的顶端忽然之间就没那么神秘了。其实就是一个 常规的.eslintrc
文件,那我们可以理解最终被 eslint
所识别的配置文件就是所有继承文件的属性合并,并且子类覆盖父类。
eslint-plugin-* 的配置形式
以eslint-plugin-react 为参考对象
// 引用规则的验证逻辑块
const allRules = {
'boolean-prop-naming': require('./lib/rules/boolean-prop-naming'),
'button-has-type': require('./lib/rules/button-has-type'),
...
};
// 导出的对象
module.exports = {
deprecatedRules,
rules: allRules,
configs: {
recommended: {
plugins: [
'react'
],
parserOptions: {
ecmaFeatures: {
jsx: true
}
},
rules: {
'react/display-name': 2,
'react/jsx-key': 2,
...
}
},
all: {
plugins: [
'react'
],
parserOptions: {
ecmaFeatures: {
jsx: true
}
},
rules: activeRulesConfig
}
}
};
以上我们可以看出,allRules
包含了所有的规则,并且所有的规则逻辑都是通过 require 的形式获取到真正的校验逻辑。
真相
至此,真相大白 ->
- 所有规则的校验逻辑都包含在
plugin
模块里面 -
config
只是一种指定了plugin对应的规则状态的配置文件 - 可以确定的就是 config已经在导出的配置结构中的plugins内包含了plugin对应的插件,以至于我们在实际
.eslintrc
文件内是不需要再重复添加到plugins的数组
内的 - 因此所依赖的插件在没有对应config文件的情况下,如果没有指定
rules
,它的规则其实是不会发生校验的 - 事实上
eslint-config-*
功能定位是偏弱化的,但是从降低耦合的角度来说这样分开更符合软件科学
个人观点:
主动去添加重复的plugin名这一行为的好处大概就是可以让不了解eslintrc继承结构
的人能从项目目录下更直观的了解该项目所依赖的插件,可以有据可查地在rules里手动去修正一些自己觉得不符合科学的规则。
编辑 by buddy Date: 2020/01/11