- @babel/core Babel 的编译器,核心 API 都在这里面,比如常见的 transform、parse
- @babel/types 用于 AST 节点的 Lodash 式工具库, 它包含了构造、验证以及变换 AST 节点的方法,对编写处理 AST 逻辑非常有用
- AST explorer 在线查看ast语法树结构
语法树分析
//转换前
import { flatten, get } from "lodash";
//转换后
import flatten from "lodash/flatten";
import get from "lodash/get";
对比两个语法树,由一个body由一个ImportDeclaration 变成了两个 ImportDeclaration;
specifiers 由ImportSpecifier 变成了ImportDefaultSpecifier
转换前语法树:
转换后语法树:
代码实现
const babel = require("@babel/core");
const t = require("babel-types");
const code = `import { flatten, get } from "lodash";`;
const importPlugin = {
visitor: {
ImportDeclaration(path, state) { //path是路径,state 表示状态、里面又一个opts代表参数对象{library: "lodash"}
let node = path.node; //获得节点 ImportDeclaration
let source = node.source; // ImportDeclaration.source
let specifiers = node.specifiers; // ImportDeclaration.specifiers
if (
state.opts.library === source.value &&
!t.isImportDefaultSpecifier(specifiers[0]) //判断当前的source是否跟目标的library一致,且第一个不是转换后的默认导入
) {
// 生成新的[importDeclaration, importDeclaration]新节点
let newSources = specifiers.map((item) => {
let defaultSpecifer = t.importDefaultSpecifier(item.local);//生成importDefaultSpecifier 默认导入
return t.importDeclaration(
[defaultSpecifer],
t.stringLiteral(`${source.value}/${item.local.name}`)
);
});
path.replaceWithMultiple(newSources); //替换
}
},
},
};
const result = babel.transform(code, {
plugins: [[importPlugin, { library: "lodash" }]],
});
//import flatten from "lodash/flatten";
//import get from "lodash/get";
console.log(result.code);