ESlint 是一种用于识别和报告在Javascript代码中发现的格式错误的工具,其目标是使代码更加一致并避免错误。它类似于JSlint和JSHint,但还有点区别:
-
ESlint 使用 Espree进行JavaScript解析;
-
ESlint 使用 AST 来评估代码中的模式;
-
ESlint 是完全可插拔的,每一条规则都是一个插件,你可以运行时添加更多;
我一开始认为 ESlint 和 webpack 有关系,实则两者是平行关系,ESlint 是可执行的命令行,通 webpack 是一样的,一开始只能对后缀.js 的文件进行处理,之后安装插件后,就能对其他文件进行处理了,这里就.vue 文件的处理插件做下解释说明:
注意:
eslint 中 extends 就像 jquery 中的 extends 一样是用来合并 eslint 中的 plugins,rules 的,碰到子配置中有 extends 会进行递归解构,不断地合并到 plugins 和 rules 两个大字段中;最后处理代码时,extends 字段是没啥作用的;如果 extends 没有路径,只是当前插件的名称,则意味着是将当前插件的 rules 作为最后一个合并对象,用来覆盖之前的所有的配置的意思;官网没有给出明确的
Vue 项目中使用 ESLint 和 Prettier - 知乎
插件中的处理器:
是用来针对不同文件做出响应的配置,细节不用深究,我们又不写 eslint 插件;
一个处理器有前置操作 preprocess 和后置操作 postprocess;
Working with Plugins - ESLint - Pluggable JavaScript linter
module.exports = {
processors: {
"processor-name": {
// takes text of the file and filename
preprocess: function(text, filename) {
// here, you can strip out any non-JS content
// and split into multiple strings to lint
return [ // return an array of code blocks to lint
{ text: code1, filename: "0.js" },
{ text: code2, filename: "1.js" },
];
},
// takes a Message[][] and filename
postprocess: function(messages, filename) {
// `messages` argument contains two-dimensional array of Message objects
// where each top-level array item contains array of lint messages related
// to the text that was returned in array from preprocess() method
// you need to return a one-dimensional array of the messages you want to keep
return [].concat(...messages);
},
supportsAutofix: true // (optional, defaults to false)
}
}
};
以文件扩展名命名的处理器
不以扩展名命名的处理器,理论上每个文件,js 的和非 js 的都会走这个处理器;如果以扩展名命名的,那么只有该扩展名的文件才会走该处理器。
如果处理器名称以 . 开头,则 ESLint 将处理器特别作为以文件扩展名命名的处理器处理,并自动将处理器应用于文件类型。人们不需要在他们的配置文件中指定以文件扩展名命名的处理器。
module.exports = {
processors: {
// This processor will be applied to `*.md` files automatically.
// Also, people can use this processor as "plugin-id/.md" explicitly.
".md": {
preprocess(text, filename) { /* ... */ },
postprocess(messageLists, filename) { /* ... */ }
}
}
}
eslint-plugin-vue 插件的配置截图如下:
这样插件就能处理.vue 结尾的文件了
如何使用插件?
Plugins - ESLint - Pluggable JavaScript linter
{
// 第一步 注入插件
"plugins": [
"jquery", // eslint-plugin-jquery
"@foo/foo", // @foo/eslint-plugin-foo
"@bar" // @bar/eslint-plugin
],
"extends": [
// 第二步 注入插件的推荐配置信息,该配置信息的key就叫recommend
"plugin:@foo/foo/recommended", // 这就是寻找插件配置的约定ESlint约定格式
"plugin:@bar/recommended"
],
"rules": {
"jquery/a-rule": "error",
"@foo/foo/some-rule": "error", // 第三步 设置插件下某规则的错误级别
"@bar/another-rule": "error"
},
"env": {
"jquery/jquery": true,
"@foo/foo/env-foo": true,
"@bar/env-bar": true,
}
// ...
}
插件中的配置
// eslint-plugin-myPlugin
module.exports = {
configs: {
myConfig: {
plugins: ["myPlugin"],
env: ["browser"],
rules: {
semi: "error",
"myPlugin/my-rule": "error",
"eslint-plugin-myPlugin/another-rule": "error"
}
},
myOtherConfig: {
plugins: ["myPlugin"],
env: ["node"],
rules: {
"myPlugin/my-rule": "off",
"eslint-plugin-myPlugin/another-rule": "off",
"eslint-plugin-myPlugin/yet-another-rule": "error"
}
}
}
};
以上配置如何引入到 eslint 中?
{
"extends": ["plugin:myPlugin/myConfig"]
// 看到这里是不是知道recommend的是怎么来的了吗?就是一个推荐配置
// 我一开始还以为是command(命令)英语不好,总是会误导思维
// 强化计算级专业英语还是比较重要的
}
至此我们来分析下@vue/eslint-config-prettier 这个插件的引入
根据扩展配置的前缀去除法,引入@vue/eslint-config-prettier 可以简写为@vue/prettier
因此,eslintrc.js 中是这样写的
module.exports = {
root: true,
env: {
node: true,
webextensions: true,
},
extends: [
'plugin:vue/essential',
'eslint:recommended',
'@vue/prettier' // 这个跳跃性是不是很大,一般人都看不懂点也点不进去
],
parserOptions: {
parser: 'babel-eslint',
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'off' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
quotes: ['warn', 'single', 'avoid-escape'],
semi: ['error', 'never']
},
}
根据 npm package.json 导出机制我们知道 export 的文件是 index.js,让我们来看看它干了啥
我们看看 index.js 有啥?
module.exports = {
plugins: ['prettier'], //
extends: [
require.resolve('eslint-config-prettier'),
require.resolve('eslint-config-prettier/vue') // 这里引入了vue配置
],
rules: {
'prettier/prettier': 'warn'
}
}
纳尼?vue 的处理插件怎么没看到?
根据 eslint-plugin-可省略原则,所以 vue/essential 全称应该是 eslint-plugin-vue/essential,essential 单词的意思是基本的,不可或缺的,这里是不是让你想骂爹,摆明不让你看懂的节奏
看到这里,就基本清晰了
总结
eslint 引用 vue 插件和 prettier 插件,并且将两者的一些配置进行了合并,避免了冲突,这样就可以让 eslint 碰到 vue 时用 eslint-plugin-vue 插件处理 vue,碰到 js 时用 @vue/prettier 处理 js 的格式,并且使得两者规则不冲突,@vue/prettier 还是 prettier 插件,只不过增加了一些 rules,来保证跟 eslint-plugin-vue 以及 eslint 自身的规则不冲突,所以这个规则要放在最后;