深入对比 eslint 插件 和 babel 插件的异同点

babel 和 eslint 都是深入基于 AST 的,一个是对比的异做代码的转换,一个是插件插件做错误检查和修复。babel 插件和 eslint 插件都能够分析和转换代码,同点那这俩到底有啥不同呢?深入
本文我们来探究下 babel 插件和 eslint 插件差别在哪里。
babel 插件
babel 的对比的异编译流程分为 parse、transform、插件插件generate 3 步,同点可以指定插件,深入在遍历 AST 的对比的异时候会合并调用 visitor。
比如我们写一个在 console.xx 的插件插件参数插入文件名 + 行列号的插件:
对函数调用节点(CallExpression)的 callee 属性进行检查,如果是同点 console.xx 的 api,则在 arguments 中插入一个 StringLiteral 的深入字符串字面量节点,值为文件名 + 行列号。对比的异
const targetCalleeName = [log,插件插件 info, error, debug].map(item => `console.${item}`); const parametersInsertPlugin = ({ types }, options) => { return { visitor: { CallExpression(path, state) { const calleeName = path.get(callee).toString() if (targetCalleeName.includes(calleeName)) { const { line, column } = path.node.loc.start; path.node.arguments.unshift(types.stringLiteral(`${options.file.filename}: (${line}, ${column})`)) } } } } } module.exports = parametersInsertPlugin;然后使用 babel core 的 api 进行代码编译,并调用插件:
const { transformFileSync } = require(@babel/core); const insertParametersPlugin = require(./plugin/parameters-insert-plugin); const path = require(path); const inputFilePath = path.join(__dirname, ./sourceCode.js); const { code } = transformFileSync(inputFilePath, { plugins: [insertParametersPlugin], parserOpts: { sourceType: unambiguous, plugins: [jsx] } }); console.log(code);当源码为下面的云南idc服务商代码时:
console.log(1); function func() { console.info(2); } export default class Clazz { say() { console.debug(3); } render() { return <div>{console.error(4)}</div> } }目标代码为:

可以看到,在 console.xx 的 api 调用处插入了文件名和行列号的参数。
这就是一个 babel 插件做代码转换的例子。
我们从中能总结出 babel 插件的特点:
插件的形式是函数返回一个对象,对象的 visitor 属性声明对什么节点做什么处理
visitor 函数可以通过 path 的 api 来对 ast 增删改
修改后的 ast 会打印成目标代码
eslint 插件
eslint 插件也会对代码进行 parse,查找要检查的 AST,之后进行检查和报错,但不一定会修复代码,只有指定了 fix 才会进行修复。
我们写一个检查对象格式的 eslint 插件。
需求时把下面的代码格式进行检查和修复:
const obj = { a: 1,b: 2, c: 3 }变成这种:
const obj = { a: 1, b: 2, c: 3 }eslint 是可以查找某个 AST 关联的 token 的,也就是我们可以拿到对象的每一个属性开始和结束的 token 还有行列号,
我们要校验上一个属性结束的 token 的WordPress模板行号要等于下一个属性开始的 token 的行号。
所以就是这样写:
指定对 ObjectExpression 也就是 {} 表达式的每一个属性的开始和结束 token 的行号做检查,如果不是下一个属性是上一个属性的 +1 行,那就报错。
并且,还可以指定如何修复,我们这里的错误的修复方式就是把两个 token 之间的部分替换为换行符(os.EOL) + tab。
const os = require(os); module.exports = { meta: { fixable: true }, create(context) { const sourceCode = context.getSourceCode(); return { ObjectExpression(node) { for (let i = 1; i < node.properties.length; i ++) { const firstToken = sourceCode.getTokenAfter(node.properties[i - 1]); const secondToken = sourceCode.getFirstToken(node.properties[i]); if(firstToken.loc.start.line !== secondToken.loc.start.line - 1) { context.report({ node, message: 对象属性之间不能有空行, loc: firstToken.loc, *fix(fixer) { yield fixer.replaceTextRange([firstToken.range[1],secondToken.range[0]], os.EOL + t); } }); } } } }; } };这样就完成了对象格式的检查和自动修复。
这个插件文件名命名为 object-property-format,然后我们使用 api 的方式调用下:
首先,引入 eslint 模块,创建 ESLint 对象:
const { ESLint } = require("eslint"); const engine = new ESLint({ fix: false, overrideConfig: { parser: @babel/eslint-parser, parserOptions: { sourceType: "unambiguous", requireConfigFile: false, }, rules: { "object-property-format": "error" } }, rulePaths: [./], useEslintrc: false });这里把配置文件关掉(useEslintrc: false),只用这里的的配置(overrideConfig)。
我们指定用 babel 的 parser(@babel/eslint-parser),免费信息发布网并且不需要 babel 配置文件。之后引入刚才我们写的那个 rule,也就是 object-property-format,报错级别设置为 error。
还需要指定 rulePaths,也就是告诉 eslint 去哪里查找 rule。
之后,我们调用 lintText 的 api 进行 lint:
(async function main() { const results = await engine.lintText(` const obj = { a: 1,b: 2, c: 3 } `); console.log(results[0].output); const formatter = await engine.loadFormatter("stylish"); const resultText = formatter.format(results); console.log(resultText); })()对于结果,我们使用内置的 formater 格式化了一下。
用 node 执行,结果如下:

可以看到,eslint 检查出了对象格式的两处错误。
为什么没有修复呢?因为没开启 fix 啊,eslint 需要开启 fix 才会修复代码。
把 Eslint 的 fix option 修改为 true,再试一下:

可以看到,没有报错了,而且代码也进行了修复。
这就是一个 eslint 插件做代码格式检查和修复的例子。
我们从中总结出 eslint 插件的 rule 的特点:
rule 的形式是对象,create 属性是一个函数,返回一个对象,指定对什么 AST 做什么检查和修复
AST 处理函数可以通过 context 的 api 来拿到源码不同位置的 token 来进行格式的检查
fix 函数可以拿到 fixer 的 api,来对某个位置的代码进行字符的增删改
默认不会修复代码,需要指定 fix 才会进行修复
eslint 插件和 babel 插件的异同
我们把总结的 babel 插件和 eslint 插件的特点拿到一起对比下。(这里的 eslint 插件严格来说是指的 eslint 的 rule,eslint 插件可以包含多个 rule。)
babel 插件:
插件的形式是函数返回一个对象,对象的 visitor 属性声明对什么节点做什么处理
visitor 函数可以通过 path 的 api 来对 ast 增删改
修改后的 ast 会打印成目标代码
eslint 插件:
rule 的形式是对象,create 属性是一个函数,返回一个对象,指定对什么 AST 做什么检查和修复
AST 处理函数可以通过 context 的 api 来拿到源码不同位置的 token 来进行格式的检查
fix 函数可以拿到 fixer 的 api,来对某个位置的代码进行字符的增删改
默认不会修复代码,需要指定 fix 才会进行修复
我们来对比下两者的异同:
从形式上来说,eslint 的 rule 是对象-函数-对象的形式,而 babel 插件是函数-对象的形式,多的部分是 eslint rule 的元信息,也就是 meta 属性。这是两者设计上的不同。
babel 插件和 eslint rule 都可以遍历节点,指定对什么节点做处理,但是 babel 插件可以通过 path 的 api 来增删改 AST,而 eslint 则是通过 context.getSourceCode() 拿到 sourceCode,然后通过 sourceCode 的 api 进行格式的检查,最后修复还要通过 fixer 的 api。
babel 插件的改动默认就是生效的,最多传入 options 进行控制,而 eslint 的 fix 功能只有开启才生效。
eslint 的 AST 中记录了在源码中 range 信息,可以根据 range 信息查找 token,但其实 babel 也可以,babel parser 也可以指定 ranges、tokens


也就是说理论上基于 babel 完全可以实现 eslint 的功能,只不过两者 api 设计上的不同,导致了两者适合的场景不同。
babel 是通过 path api 进行 AST 增删改,适合做代码分析和转换。
eslint 是通过 sourceCode 和 fixer api 进行代码格式的检查和 fix,适合做错误检查和修复。
但是,从本质上来说,两者编译流程上差别并不大。
总结
我们写了一个在 console.xx api 插入参数的 babel 插件,又写了一个检查和修复对象格式的 eslint 插件,分析了两者的特点,然后做了下对比。
两者插件形式上不同,api 也不同:
babel 是通过 path 的 api 对 AST 进行增删改,而 eslint 是通过 sourceCode 的 api 进行代码格式的检查,通过 fixer 的 api 进行修复。这就导致了 babel 插件更适合做代码转换,eslint 插件更适合做代码格式的校验和修复。但实际上 babel 也能做到 eslint 一样的事情,两者本质上的编译流程是差不多的。
这篇文章把 babel 插件和 eslint 插件放到一起进行了对比,讲述了两者本质的相同和 api 的不同,希望能够帮大家更好的掌握 babel 和 eslint 插件。
相关文章
- 摘要:在电脑游戏和办公工作中,键盘是我们经常使用的输入设备之一。为了提高输入效率和舒适度,越来越多的人开始选择机械键盘。而黑爵机械键盘作为市场上知名品牌之一,以其高品质、耐用性和极致敲击...2025-11-05
手机视频传输教程(简单操作,手机变身移动音乐播放器,发挥无限创意)
摘要:随着手机的普及和功能的不断升级,我们可以通过手机拍摄或下载各种视频。有时候,我们希望将这些视频转换为音频格式,以便在MP3播放器上欣赏。本文将向您介绍如何使用手机将视频传输为MP3...2025-11-05使用U盘安装原版ISO系统的完整教程(详细步骤教你如何使用U盘安装原版ISO系统)
摘要:在安装操作系统时,使用U盘安装原版ISO系统是一种常见且方便的方法。本文将详细介绍如何使用U盘来安装原版ISO系统,帮助读者轻松完成系统安装。1.准备工作:确保U盘具备足够...2025-11-05荣威i6(探索荣威i6的马力性能,了解其强大的动力输出能力)
摘要:随着汽车科技的不断发展,马力作为衡量汽车动力性能的重要指标之一,日益受到消费者的重视。而荣威i6作为一款备受瞩目的豪华轿车,以其出色的马力性能成为了消费者关注的焦点。本文将以荣威i...2025-11-05- 摘要:如今,耳机已经成为我们生活中不可或缺的一部分。小米作为中国知名品牌,一直致力于为消费者提供高品质且价格合理的产品。在这个领域里,小米199耳机无疑是一款备受关注的产品。本文将对其进...2025-11-05
乌鸦的视觉能力与行为习性(洞察世界的黑羽使者——乌鸦的视觉系统和行为适应性)
摘要:乌鸦是一种聪明而神秘的鸟类,在人类文化中一直被赋予了智慧和预兆的象征意义。然而,很少有人真正了解乌鸦的视觉能力和行为习性。本文将深入探讨乌鸦的视觉系统,揭示其独特的视觉能力和行为适...2025-11-05

最新评论