-
Notifications
You must be signed in to change notification settings - Fork 93
Open
Description
调试网站
babel
const template = require('@babel/template').default;
const generate = require("@babel/generator").default;
const ast = template.ast(`
// JS
var a = 'abcd'
`);
ast.kind = 'let';
ast.declarations[0].init.value = 1234;
console.log(ast.declarations[0].init);
console.log(generate(ast).code);这段代码通过AST把var a = 'abcd'转化为let b = 1234
babel-plugins
babel插件开发,plugin字段配合visitor筛选代码实现转化,转换的时候,是插件开始起作用的时候,babel给我们提供了一个visitor的规范,让我们进入到这个流程中,我们可以通过visitor来定义我们的访问逻辑
visitor支持很多类型,比如VariableDeclaration,FunctionDeclaration ,ImportDeclaration 等,具体可以从AST测试网站展开分析
const {
transform
} = require("@babel/core");
module.exports = async (option, options) => {
let {
script,
allScript,
isExistScript,
scriptLang,
template,
templateLang,
templateComponentName,
style,
styleLang,
isExistStyle
} = option
const result = await new Promise((resolve, reject) => {
const defaultOption = {
plugins: [
require("@babel/plugin-proposal-class-properties"),
{
visitor: {
ArrayExpression(path) {
console.log(path.node)
}
}
}
],
presets: [
[
require("@babel/preset-react"),
{
"pragma": "h",
}
]
]
}
// comibine option
const finalOptions = Object.assign({}, defaultOption, {
...options
});
transform(allScript, {
...finalOptions
}, (err, result) => {
if (err) {
reject(err)
} else {
// console.log(result)
resolve(result)
}
});
})
return result
}访问者模式
可以在方法名用|来匹配多种不同的type,使用相同的处理函数
visitor: {
"ClassExpression|VariableDeclaration"(path) {
console.log(path.node.body)
}
}遍历
可以手动查找就不要遍历
path.node.params.forEach(function() {
// ...
});获取子节点的path
BinaryExpression(path) {
path.get('left');
},
Program(path) {
path.get('body.0');
}获取父节点的path
findParent获取对应的子节点的
path.find((path) => path.isObjectExpression());
path.find((path) => path.isReturnStatement()); //获取return的地方babel-types
配合babel-types工具进行代码替换增加等
const t = require("babel-types");用多节点替换单节点
ReturnStatement(path) {
path.replaceWithMultiple([
t.expressionStatement(t.stringLiteral("Is this the real life?")),
t.expressionStatement(t.stringLiteral("Is this just fantasy?")),
t.expressionStatement(t.stringLiteral("(Enjoy singing the rest of the song in your head)")),
]);
}还可以替换代码,不过经过测试,它有局限性,官方文档也不建议使用
FunctionDeclaration(path) {
path.replaceWithSourceString(`function add(a, b) {
return a + b;
}`);
}技巧
利用visitor访问者模式获取函数片段,然后通过path.get(类型)一层一层定位到对应的子路径然后执行path.xxx改造代码片段,获取子属性可以先在AST测试网站先查找结果
visitor: {
"ClassExpression"(path, { opts }) {
// 筛选class myAbcAbc extends WeElement类
if (path.node.superClass.name === 'WeElement' && path.get("body.body")) {
console.log('---------------')
path.get("body.body").forEach((ClassMethod) => {
// 筛选render() {}函数
if (ClassMethod.node.key.name === 'render') {
console.log(ClassMethod.type)
ClassMethod.remove()
}
})
}
}
}loader里面获取文件的路径:
const filename = this.resourcePath;踩过的坑
类里面的方法要使用 ClassMethod 匹配,不能使用 FunctionExpression 匹配。
参考网站
Metadata
Metadata
Assignees
Labels
No labels