【问题标题】:How to write a babel js plugin that passes output to other plugins?如何编写一个将输出传递给其他插件的 babel js 插件?
【发布时间】:2018-02-04 04:36:43
【问题描述】:

我正在尝试编写一个 babel 插件,将内容预先/附加到文件中 - 例如;将行 console.log("start of " + __filename);console.log("end of " + __filename); 添加到每个文件中。

到目前为止,我已经设法编写了一个完全执行此操作的访问者,但是在我的插件运行之前或之后,现有代码不会被任何其他插件修改。

例如,我有以下文件:

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

console.dir({ foo, bar });

单独使用 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 });

但是,一旦我将自己的插件添加到此;似乎 env 预设被跳过以支持我自己的插件 - 但是我希望应用这两个插件(最好是我的插件)。


到目前为止,我的插件代码如下:

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
  }
}

而我的.babelrc 很简单:

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

这是产生输出:

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

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

谁能建议我缺少什么让 babel 将我的插件与其他插件链接起来,以允许我组合使用多个插件?

【问题讨论】:

    标签: javascript babeljs babel-plugin


    【解决方案1】:

    这是产生输出:

    鉴于您正在使用 eval,并且您正在使用错误数量的参数调用您的 transform 函数,这不可能是真的 :)

    写你要找的东西的正确方法是

    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());
          }
        }
      };
    }
    

    通过使用unshiftContainerpushContainer,Babel 可以将这些节点排队等待其他插件处理。这也使用template 为您的两个 sn-ps 生成 AST。

    【讨论】:

    • 啊,谢谢!为了这个例子,我把它剪掉了,似乎我错过了一些。 unshiftContainer/pushContainer 确实是我所缺少的。
    • 为了未来对上述变换功能感到困惑的读者的利益;我已经编辑了问题以更正函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    相关资源
    最近更新 更多