目的
只是学习概念,还不够需要实战敲一下 才靠谱
实战需求
思路分析
代码实现
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const types = require("@babel/types");
const generate = require("@babel/generator").default;
const sourceCode = `
console.log(123);
function func() {
console.info(234);
}
export default class Test {
say() {
console.debug(345);
}
render() {
return <div>{console.error(456)}</div>
}
}
`;
const ast = parser.parse(sourceCode, {
sourceType: "unambiguous",
plugins: ["jsx"],
});
traverse(ast, {
CallExpression(path, state) {
if (
types.isMemberExpression(path.node.callee) &&
path.node.callee.object.name === "console" &&
["log", "info", "error", "debug"].includes(path.node.callee.property.name)
) {
const { line, column } = path.node.loc.start;
path.node.arguments.unshift(
types.stringLiteral(`filename: (${line}, ${column})`)
);
}
},
});
const { code, map } = generate(ast);
console.log(code);
结果展示
简化判断条件
改个需求试试?
这个事情 工作遇到就很烦,但 这里不是工作 哈哈
分析
代码实现
改成插件试试
代码实现
const targetCalleeName = ['log', 'info', 'error', 'debug'].map(item => `console.${item}`);
module.exports = function({types, template}) {
return {
visitor: {
CallExpression(path, state) {
if (path.node.isNew) {
return;
}
const calleeName = generate(path.node.callee).code;
if (targetCalleeName.includes(calleeName)) {
const { line, column } = path.node.loc.start;
const newNode = template.expression(`console.log("${state.filename || 'unkown filename'}: (${line}, ${column})")`)();
newNode.isNew = true;
if (path.findParent(path => path.isJSXElement())) {
path.replaceWith(types.arrayExpression([newNode, path.node]))
path.skip();
} else {
path.insertBefore(newNode);
}
}
}
}
}
}
通过 @babel/core 的 transformSync 方法来编译代码,并引入上面的插件:
const { transformFileSync } = require('@babel/core');
const insertParametersPlugin = require('./plugin/parameters-insert-plugin');
const path = require('path');
const { code } = transformFileSync(path.join(__dirname, './sourceCode.js'), {
plugins: [insertParametersPlugin],
parserOpts: {
sourceType: 'unambiguous',
plugins: ['jsx']
}
});
console.log(code);
把前面调用 parse、traverse、generate 的代码改造成了 babel 插件的形式,只需要提供一个转换函数,traverse 的过程中会自动调用。
可以试试, 运行 babel 环境可以使用这个 codesandbox.io/p/sandbox/y…