Webpack 插件使用 asm 更改内容
Webpack plugin change content with asm
问题
你好,我正在尝试编写一个插件并使用 ast 来解析文件。但我无法更改代码。例如,此代码不会将 div 更改为标签。 ast 的正确修改方法是什么?
apply(compiler) {
compiler.hooks.normalModuleFactory.tap('MyPlugin', (factory) => {
factory.hooks.parser.for('javascript/auto').tap('MyPlugin', (parser, options) => {
parser.hooks.program.tap('MyPlugin', (ast, comments) => {
if (parser.state &&
parser.state.module &&
parser.state.module.resource.indexOf('node_modules') === -1) {
if (parser.state.module.resource.endsWith('tsx')) {
var g = ast.body.filter(n=> n.type === 'ExportNamedDeclaration');
for (let a of g) {
var decl = a.declaration.declarations;
if (decl && decl[0]) {
decl[0].init.body.body[0].argument.arguments[0].raw = 'label';
decl[0].init.body.body[0].argument.arguments[0].value = 'label';
}
}
}
}
});
});
});
}`
我只需要将 div 更改为 return 块中的标签或将数据属性添加到 div。我不想使用正则表达式并替换所有文件内容,我想用 ast 来实现。
MyComponent.tsx可以如下:
import * as React from 'react';
import * as style from './MyComponent.css';
export const MyComponent = (props) => {
return (
<div className={style['test']}>bla bla</div>
);
};
可能有人可以提供一个小例子来改变 webpack 插件中抽象语法树的一些东西。
正如评论中提到的和在 this question 中的 webpack 代码中指出的那样,webpack 忽略了在点击中更改解析器 AST 的尝试。
插件应该使用 ast 作为只读映射来在 dependency graph 中构建新的依赖项。 (这在排序和并行执行方面不那么脆弱,因为多个插件可以添加到依赖关系图中,而不会通过更改引用 AST 使彼此无效。)
基于 i18n-lang 和定义插件,使用 ast 为您的转换构建依赖项的示例如下所示:
"use strict";
const pluginName = 'MyPlugin';
const NullFactory = require('webpack/lib/NullFactory');
const ConstDependency = require("webpack/lib/dependencies/ConstDependency");
class MyPlugin {
apply(compiler) {
compiler.hooks.compilation.tap(
"MyPlugin",
(compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(ConstDependency, new NullFactory());
compilation.dependencyTemplates.set(
ConstDependency,
new ConstDependency.Template()
);
});
compiler.hooks.normalModuleFactory.tap('MyPlugin', (factory) => {
factory.hooks.parser.for('javascript/auto').tap('MyPlugin', (parser, options) => {
parser.hooks.program.tap('MyPlugin', (ast, comments) => {
if (parser.state &&
parser.state.module &&
parser.state.module.resource.indexOf('node_modules') === -1) {
if (parser.state.module.resource.endsWith('tsx')) {
var g = ast.body.map(n => {
try {
let {expression:{left:{property:{name:my}}, right:{body:{body:[{argument:{arguments:[div]}}]}}}} = n
return my == 'MyComponent' && div.value == 'div' ? div: false
} catch(e) {
return false;
}
}).filter(e=>e);
for (let div of g) {
let dep = new ConstDependency(JSON.stringify('label'), div.range);
dep.loc = div.loc;
parser.state.current.addDependency(dep);
}
}
}
});
});
});
}
}
module.exports= MyPlugin;
解析器提供的 ast
可能会因不同的加载器和输入的变化而有很大差异。
问题
你好,我正在尝试编写一个插件并使用 ast 来解析文件。但我无法更改代码。例如,此代码不会将 div 更改为标签。 ast 的正确修改方法是什么?
apply(compiler) {
compiler.hooks.normalModuleFactory.tap('MyPlugin', (factory) => {
factory.hooks.parser.for('javascript/auto').tap('MyPlugin', (parser, options) => {
parser.hooks.program.tap('MyPlugin', (ast, comments) => {
if (parser.state &&
parser.state.module &&
parser.state.module.resource.indexOf('node_modules') === -1) {
if (parser.state.module.resource.endsWith('tsx')) {
var g = ast.body.filter(n=> n.type === 'ExportNamedDeclaration');
for (let a of g) {
var decl = a.declaration.declarations;
if (decl && decl[0]) {
decl[0].init.body.body[0].argument.arguments[0].raw = 'label';
decl[0].init.body.body[0].argument.arguments[0].value = 'label';
}
}
}
}
});
});
});
}`
我只需要将 div 更改为 return 块中的标签或将数据属性添加到 div。我不想使用正则表达式并替换所有文件内容,我想用 ast 来实现。 MyComponent.tsx可以如下:
import * as React from 'react';
import * as style from './MyComponent.css';
export const MyComponent = (props) => {
return (
<div className={style['test']}>bla bla</div>
);
};
可能有人可以提供一个小例子来改变 webpack 插件中抽象语法树的一些东西。
正如评论中提到的和在 this question 中的 webpack 代码中指出的那样,webpack 忽略了在点击中更改解析器 AST 的尝试。
插件应该使用 ast 作为只读映射来在 dependency graph 中构建新的依赖项。 (这在排序和并行执行方面不那么脆弱,因为多个插件可以添加到依赖关系图中,而不会通过更改引用 AST 使彼此无效。)
基于 i18n-lang 和定义插件,使用 ast 为您的转换构建依赖项的示例如下所示:
"use strict";
const pluginName = 'MyPlugin';
const NullFactory = require('webpack/lib/NullFactory');
const ConstDependency = require("webpack/lib/dependencies/ConstDependency");
class MyPlugin {
apply(compiler) {
compiler.hooks.compilation.tap(
"MyPlugin",
(compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(ConstDependency, new NullFactory());
compilation.dependencyTemplates.set(
ConstDependency,
new ConstDependency.Template()
);
});
compiler.hooks.normalModuleFactory.tap('MyPlugin', (factory) => {
factory.hooks.parser.for('javascript/auto').tap('MyPlugin', (parser, options) => {
parser.hooks.program.tap('MyPlugin', (ast, comments) => {
if (parser.state &&
parser.state.module &&
parser.state.module.resource.indexOf('node_modules') === -1) {
if (parser.state.module.resource.endsWith('tsx')) {
var g = ast.body.map(n => {
try {
let {expression:{left:{property:{name:my}}, right:{body:{body:[{argument:{arguments:[div]}}]}}}} = n
return my == 'MyComponent' && div.value == 'div' ? div: false
} catch(e) {
return false;
}
}).filter(e=>e);
for (let div of g) {
let dep = new ConstDependency(JSON.stringify('label'), div.range);
dep.loc = div.loc;
parser.state.current.addDependency(dep);
}
}
}
});
});
});
}
}
module.exports= MyPlugin;
解析器提供的 ast
可能会因不同的加载器和输入的变化而有很大差异。