У 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
.
person
Domi
schedule
06.12.2019