Babel插件运行顺序

18
TL;DR: 如何指定 Babel 插件运行的顺序?Babel 如何确定插件的顺序?除了查看 Babel 源代码,还有没有规范说明它的工作原理?
我正在开发自己的 Babel 插件。我注意到,当我运行它时,我的插件会在其他 es2015 插件之前运行。例如,有以下代码:
const a = () => 1

以及像访问者一样的人:

visitor: {
  ArrowFunctionExpression(path) {
    console.log('ArrowFunction')
  },
  FunctionExpression(path) {
    console.log('Function')
  },
}

我的插件观察的是箭头函数(而不是普通函数)。我尝试过在Babel配置中更改插件的顺序,但这并没有改变任何东西:

plugins: ['path_to_myplugin', 'transform-es2015-arrow-functions'],
plugins: ['transform-es2015-arrow-functions', 'path_to_myplugin'],

另一方面,看起来顺序确实很重要:

https://phabricator.babeljs.io/T6719

---- 编辑 ----

我发现如果我将我的访问器写成以下形式:

  ArrowFunctionExpression: {
    enter(path) {
      console.log('ArrowFunction')
    }
  },
  FunctionExpression: {
    exit(path) {
      console.log('Function')
    }
  },

两个函数都被调用了。因此,执行顺序似乎是:myplugin_enter -> other_plugin -> myplugin_exit。换句话说,在某个内部管道中,myplugin似乎在other_plugin之前。然而,主要问题仍然相同 - 插件在管道中的顺序应该以某种方式确定和配置。

2个回答

19

插件的顺序基于你的 .babelrc 文件中事物的顺序,插件在预设之前运行,每组在较早的插件/预设之前运行较晚的插件/预设。

但最重要的是,排序是针对AST节点的。每个插件不会执行完整的遍历,Babel会并行地运行所有插件进行单次遍历,每个节点依次处理,运行每个插件的每个处理程序。


1
谢谢,但即使我禁用了我的.babelrc并且我的“插件顺序”如下:plugins: ['transform-es2015-arrow-functions', 'path_to_myplugin'],transform-es2015-arrow-functions的enter函数显然在myplugin的enter函数之后被调用。为什么会这样?除了处理预设(这不是非常细粒度的控制),是否有一种方法来配置babel中的插件顺序? - Tomas Kulich
4
可以的,"group" 在这里指的是一组插件或预设的集合,每个集合会按照特定的顺序运行其中的插件或预设,先运行后面的插件或预设,再运行前面的插件或预设。 - Tomas Kulich
2
我有类似的情况。您在更高的作用域中是否有另一个访问者函数,可能是针对Program调用path.traverse并使用您实际的访问者?我想这会首先被调用。 - Fabian Zeindl
2
@loganfsmyth - 我看到插件按顺序运行。https://gist.github.com/jamestalmage/885e1d0d732557cfb5cf854aee04fd19?ts=2 - James Talmage
我在使用webpack的UglifyJs插件时遇到了非确定性错误,有时会因为lambda没有被转换成函数而失败。真的很想知道发生了什么XD。 - Andy
我发现至少对于Babel 6.26.3及以上版本,这是不正确的。从https://babeljs.io/docs/en/6.26.3/plugins#plugin-preset-ordering中可以看到,“插件排序是从前往后的”,最新版本也是如此。这个答案似乎是在Babel 6.0.0发布后两个月左右给出的。我不确定这个答案适用于哪个版本。我没有追踪过Babel是否改变了这种行为。 - Jack Lu

8

基本上,@loganfsmyth所写的是正确的;插件排序本身(可能)没有更多的魔力。

至于我的问题,我的困惑是由箭头函数转换方式造成的。即使babel-plugin-transform-es2015-arrow-functions插件比我的插件更早地混淆了代码,它也不会从ast中删除原始箭头函数ast节点,因此后来的插件仍然可以看到它。

教训:在处理Babel时,不要低估所需的调试打印语句数量,以理解发生的情况。


2
学习编程:如果你之前没有太多经验,在学习的第一年或两年(我这里还算是很宽容了),就要忘掉正常的社交生活。 - ZenVentzi
只需使用 AST Explorer。 - wintercounter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接