babel-import-util
Makes it easier for a babel plugin to emit imported names. Key benefits:
- the output composes correctly with subsequent babel plugins, because we update Babel's understanding of the bindings
- redundant imports will be deduplicated automatically
- written in TypeScript
Usage by example:
If you want to rewrite:
myTarget('hello world');
To:
import { theMethod } from 'my-implementation';
theMethod('hello world');
Your plugin would look like this:
function testTransform(babel) {
return {
visitor: {
Program: {
enter(path, state) {
state.importUtil = new ImportUtil(babel.types, path);
},
},
CallExpression(path, state) {
let callee = path.get('callee');
if (callee.isIdentifier() && callee.node.name === 'myTarget') {
state.importUtil.replaceWith(callee, (i) =>
i.import(callee, 'my-implementation', 'theMethod')
);
}
},
},
};
}
API
import type { NodePath } from '@babel/traverse';
import type * as t from '@babel/types';
class ImportUtil {
replaceWith<T extends t.Node, R extends t.Node>(
target: NodePath<T>,
fn: (i: Importer) => R
): NodePath<R>;
insertAfter<T extends t.Node, R extends t.Node>(
target: NodePath<T>,
fn: (i: Importer) => R
): NodePath<R>;
insertBefore<T extends t.Node, R extends t.Node>(
target: NodePath<T>,
fn: (i: Importer) => R
): NodePath<R>;
importForSideEffect(moduleSpecifier: string): void;
removeImport(moduleSpecifier: string, exportedName: string): void;
removeAllImports(moduleSpecifier: string): void;
import(
target: NodePath<t.Node>,
moduleSpecifier: string,
exportedName: string,
nameHint?: string
): t.Identifier;
}