pre
和有一个更基本的用途post
:它们在所有遍历之前/之后为所有插件运行。所有插件的顺序是:
pre
适用于所有插件
visitor
适用于所有插件
post
适用于所有插件。
回答您的问题:visitor.Program.enter
并且pre
在大多数情况下表现相同,也就是说,如果您不在乎其他插件Program
在您自己的插件visitor
启动时是否已经开始访问。主要区别可以总结为两点:
pre
确保在任何插件开始遍历之前运行。
pre
确保只运行一次,而节点访问者可以运行多次,因为(您自己的或其他插件的)访问者对 AST 的更改可能保证无限量的重新访问。
插件(和预设)的执行顺序
请注意,插件的执行顺序是一个被大量讨论的开放性问题(请参阅此处了解第一个介绍),pre
并post
有助于减轻可能与其他插件发生冲突的插件的一些痛苦。
作为参考,这是 Babel7 中插件和预设的执行顺序(使用babel.config.js
下面给出的运行时):
[PLUGIN] pre plugin1
[PLUGIN] pre plugin2
[PLUGIN] pre pres2
[PLUGIN] pre pres1
[PLUGIN] Program plugin1
[PLUGIN] Program plugin2
[PLUGIN] Program pres2
[PLUGIN] Program pres1
[PLUGIN] post plugin1
[PLUGIN] post plugin2
[PLUGIN] post pres2
[PLUGIN] post pres1
参考babel.config.js
:
function makeReporterPlugin(msg) {
return () => {
return {
pre() {
console.log('[PLUGIN] pre', msg);
},
visitor: {
Program() {
console.log('[PLUGIN] Program', msg);
}
},
post() {
console.log('[PLUGIN] post', msg);
},
};
};
}
const pres1 = {
plugins: [
makeReporterPlugin('pres1')
]
};
const pres2 = {
plugins: [
makeReporterPlugin('pres2')
]
};
const plugin1 = makeReporterPlugin('plugin1');
const plugin2 = makeReporterPlugin('plugin2');
module.exports = {
"presets": [
pres1,
pres2
],
"plugins": [
plugin1,
plugin2
]
};
讨论:Babel 插件执行顺序混乱
当我写我的第一个插件时,我自己也很困惑。它似乎在 之后运行@babel/preset-env
,尽管根据插件订购的文档,presets
应该在plugins
. 但是,正如这里所解释的,实际上并不是那么简单:所有插件和预设的visitors
遍历并行,而文档中描述的顺序(预设之前的插件)仅针对每个节点单独确保,而不是针对整个 AST 遍历。pre
那个痛点是和的主要动机post
。