В чем разница между "Visitor.Program.enter()" и "pre()" в плагине Babel?

Этот плагин 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/Program.exit?

Есть ли какая-то разница?

0 ответов

Там нет разницы AFAIK. Оба вызываются до / после того, как синтаксическое дерево было полностью пройдено.

Единственное отличие состоит в том, что параметры передаются 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 с вашими опциями плагина, тогда как из pre() ты не

Есть более фундаментальное применение pre а также post: они запускаются для всех плагинов до / после всех обходов. Порядок всех плагинов:

  1. pre работает для всех плагинов
  2. visitor работает для всех плагинов
  3. post работает для всех плагинов.

Чтобы ответить на ваш вопрос: visitor.Program.enter а также pre в большинстве случаев вести себя одинаково, то есть, если вам все равно, начали ли уже посещать другие плагины Program к тому времени, когда ваш собственный плагин visitorначинается. Основное отличие можно резюмировать двумя пунктами:

  1. preгарантированно запускается до того, как любой плагин начнет обход.
  2. 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. Однако, как объясняется здесь, на самом деле это не так просто: все плагины и пресеты проходят параллельно, в то время как порядок, описанный в документации (плагины перед пресетами), гарантируется только для каждого узла индивидуально, а не для всего обхода AST.

Другие вопросы по тегам