I'm trying to write a babel plugin that prepends/appends content to a file - for example; add the lines console.log("start of " + __filename);
and 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:
'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).
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:
{
"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?
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 :)
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. This also uses template
to generate the ASTs for your two snippets.