此Babel插件:
module.exports = function(){
return {
visitor:{
Program:{
enter(){ console.log('Enter') },
exit(){ console.log('Exit') }
}
},
pre(){ console.log('Pre') },
post(){ console.log('Post') }
}
}
为任何javascript文件产生以下输出:
Pre
Enter
Exit
Post
pre()
在Program.enter()
之前被调用,而post()
在Program.exit()
之后被调用。
如果我想在AST遍历的开始/结尾运行一些代码,是否有任何理由我应该将该代码放在pre
/ post
而不是Program.enter
/ { {1}}?
有什么区别吗?
答案 0 :(得分:2)
AFAIK没有区别。完全遍历语法树之前/之后都调用它们。
唯一的区别是传递给@user.article.description
/ Program.enter
的参数与传递给Program.exit
/ pre
的参数不同。
post
例如,从module.exports = function(){
return {
visitor:{
Program:{
enter(path, state){
//path.node
//path.parent
//state.opts
},
}
},
pre(state){
//state.scope
//state.scope.globals
//state.scope.plugins
},
}
}
可以使用插件选项访问Program.enter()
,而从state.opts
则没有访问权限。
答案 1 :(得分:0)
pre
和post
有更根本的用途:它们在所有遍历之前/之后针对所有插件运行。 所有插件的顺序是:
pre
为所有插件运行visitor
为所有插件运行post
为所有插件运行。要回答您的问题:visitor.Program.enter
和pre
在大多数情况下的行为相同,也就是说,如果您不关心当时其他插件是否已经开始访问Program
您自己的插件的visitor
开始。主要区别可以概括为两点:
pre
在任何插件开始遍历之前运行。pre
只能运行一次,而节点访问者可以运行多次,因为(您自己或其他插件的)访问者对AST进行的更改可能会无限期地运行再次访问的数量。请注意,插件的执行顺序是一个尚未解决的悬而未决的问题(see here for a first introduction),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/preset-env
之后运行,尽管according to the docs on plugin ordering,presets
应该在plugins
之后运行。但是,as explained here实际上并不是那么简单:所有插件和预设都可以并行遍历,而docs中描述的顺序(预设之前的插件)仅针对每个节点(而不是整个AST遍历)得到保证。