简体   繁体   English

如何编写将输出传递到其他插件的babel js插件?

[英]How to write a babel js plugin that passes output to other plugins?

I'm trying to write a babel plugin that prepends/appends content to a file - for example; 我正在尝试编写一个babel插件,以将内容添加/添加到文件中-例如; add the lines console.log("start of " + __filename); 添加以下行console.log("start of " + __filename); and console.log("end of " + __filename); console.log("end of " + __filename); to each file. 到每个文件。

So far, I've managed to write a visitor that does exactly this, however the existing code doesn't get modified by any other plugins before OR after my plugin operates. 到目前为止,我已经设法编写了一个完全做到这一点的访客,但是在插件运行之前或之后,现有的代码不会被任何其他插件修改。

For example, I have the following file: 例如,我有以下文件:

import * as foo from 'foo';
import * as bar from 'bar';

console.dir({ foo, bar });

Using the env preset alone (ie. without my plugin) and the option targets.node: 'current' I end up with the output - note that es6 imports have been transformed into commonjs requires: 单独使用env预设(即没有我的插件)和选项targets.node: 'current'我最终得到输出-请注意,es6导入已转换为commonjs要求:

'use strict';
var _foo = require('foo');
var foo = _interopRequireWildcard(_foo);
var _bar = require('bar');
var bar = _interopRequireWildcard(_bar);
function _interopRequireWildcard(obj) { /* resolve commonjs or es6 module */ }
console.dir({ foo, bar });

However as soon as I add my own plugin to this; 但是,一旦我添加了自己的插件; it appears that the env preset is skipped in favour of my own plugin - however I'd like both plugins to be applied (mine first, preferably). 看来该env预置有利于自己的插件的跳过-但我想这两个插件应用(我的第一次,最好)。


So far, my plugin code looks like: 到目前为止,我的插件代码如下:

module.exports = function wrapModule(babel) {

  const prepend = transform(`console.log("start of " + __filename);`)
  const append = transform(`console.log("end of " + __filename);`)
  return {
    visitor: {
      Program(path, {opts}) {
        path.replaceWith(t.program([...prepend, ...path.node.body, ...append]))
        path.stop()
      }
    }
  }

  function transform(content) {
    return babel.transform(content).ast.program.body
  }
}

and my .babelrc is simply: 而我的.babelrc很简单:

{
  "presets": [[
    "env", { "targets": { "node": "current" } }
  ]],
  "plugins": [
    "./wrapper-babel-plugin"
  ]
}

And this is producing the output: 这将产生输出:

console.log("start of " + __filename);
import * as foo from 'foo';
import * as bar from 'bar';

console.dir({ foo, bar });
console.log("end of " + __filename);

Can anyone suggest what I'm missing to have babel chain my plugin with other plugins, to allow me to use multiple plugins in combination? 谁能建议我缺少将Babel与其他插件链接的插件,让我可以结合使用多个插件吗?

And this is producing the output: 这将产生输出:

Given that you are using eval , and you are calling your transform function with the wrong number of arguments, that can't possibly be true :) 假设您正在使用eval ,并且正在使用错误数量的参数调用您的transform函数,那不可能是真的:)

The correct way to write what you're looking for would be 编写所需内容的正确方法是

export default function wrapModule({ template }) {
  const prepend = template(`console.log("start of " + __filename);`);
  const append = template(`console.log("end of " + __filename);`);

  return {
    visitor: {
      Program(path, {opts}) {
        path.unshiftContainer("body", prepend());
        path.pushContainer("body", append());
      }
    }
  };
}

By using unshiftContainer and pushContainer Babel can queue up those nodes for processing by other plugins. 通过使用unshiftContainerpushContainer Babel可以将那些节点排队,以供其他插件处理。 This also uses template to generate the ASTs for your two snippets. 这也使用template为您的两个片段生成AST。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM