Javascript 有没有一种方法可以连接到Webpack';是AST让它识别新的模块格式吗?
短版: 我们如何处理最终输出包的AST,以及加载程序中文件的AST?在这两种情况下,我都希望操作现有的AST,而不是我正在做的事情,即解析源代码并生成一个新的AST。我做的很慢,而且我知道Webpack肯定已经做了AST,所以我想避免重复工作 长版本: 例如,假设我有一堆文件,其格式与AMD模块类似(但不完全相同):Javascript 有没有一种方法可以连接到Webpack';是AST让它识别新的模块格式吗?,javascript,node.js,webpack,Javascript,Node.js,Webpack,短版: 我们如何处理最终输出包的AST,以及加载程序中文件的AST?在这两种情况下,我都希望操作现有的AST,而不是我正在做的事情,即解析源代码并生成一个新的AST。我做的很慢,而且我知道Webpack肯定已经做了AST,所以我想避免重复工作 长版本: 例如,假设我有一堆文件,其格式与AMD模块类似(但不完全相同): module({ Foo: '/path/to/Foo', Bar: '/path/to/Bar', Baz: '/path/to/Baz', }, function(
module({
Foo: '/path/to/Foo',
Bar: '/path/to/Bar',
Baz: '/path/to/Baz',
}, function(imports) {
console.log(imports) // {Foo:..., Bar:... Baz:...}
})
不同之处在于,它被称为模块
,而不是定义
,依赖项参数是导入名称到模块路径的映射,而不是模块路径数组,模块正文函数接收一个包含所有请求导入的导入
对象,而不是每个请求导入一个参数
以上类似于AMD格式的以下内容,具有相同的输出:
define([
'/path/to/Foo',
'/path/to/Bar',
'/path/to/Baz',
], function(Foo, Bar, Baz) {
console.log({Foo, Bar, Baz}) // {Foo:..., Bar:... Baz:...}
})
为了最终构建一个包含以此module()
格式编写的文件的捆绑包,建议采用何种方式连接到Webpack以使Webpack能够理解文件(能够知道文件具有哪些依赖关系)
我已经尝试过一种方法:我制作了一个自定义加载程序,它以字符串形式接收文件源代码,对其进行解析并创建AST,转换AST,然后以Webpack能够理解的AMDdefine()
格式输出代码
然而,我觉得这样做很慢,因为如果有很多文件,而且文件很大,那么解析和生成每个文件的AST似乎是多余的,因为我打赌Webpack从一开始就已经这样做了。有没有办法从Webpack获取AST并在Webpack想要扫描其依赖项之前对其进行转换,以便我可以将AST转换为AMD格式(或任何公认的格式),以便Webpack最终可以处理该文件?还有其他方法吗?我想您会发现在依赖项解析过程中使用了加载程序 基本上,解析器需要源代码才能完成其工作。因此,在当前解析阶段遇到的任何import/require语句(依赖项)都需要:a。被解决和:b。必须先加载,然后才能对其进行分析。如果您挂接到增强解析包的“解析步骤”,您可以console.log退出解析程序转换的状态转换,这些状态转换通常以触发“创建模块”插件而告终 钩住“解决步骤”: 钩住“创建模块”:
希望这能有所帮助。我正在寻找类似的东西,想要操纵ast,但没有示例或有用的文档 用谷歌搜索它只浪费了我2个小时的时间,但由于完成了一半且不可理解的文档,我确实想到了这个(尽管不起作用): 这会给我一个if语句的节点,对于其他类型的节点,您可以查看 我尝试返回另一个节点,但是创建一个节点需要大量的工作,而且似乎没有一个简单的方法来完成 为什么还要费心在网页包中这么做呢?webpack贡献者制作了一个很好的产品,但没有人知道它是如何工作的,因为它的许多功能都没有文档 作为一个babel插件,你可能会做得更好,它写得很好,可以理解 我和巴贝尔在20分钟内完成了这项工作:
module.exports = function ({ types: t }) {
return {
visitor: {
IfStatement(path, file) {
path.node.test = {
"type": "BooleanLiteral",
"start": path.node.test.start,
"end": path.node.test.start+4,
"loc": {
"start": {
"line": 7,
"column": path.node.test.loc.start.column
},
"end": {
"line": 7,
"column": path.node.test.loc.start.column+4
}
},
"value": true
}
// debugger;
// path.unshiftContainer('body', t.expressionStatement(t.stringLiteral('use helloworld')));
}
}
};
};
在webpack.config.js中:
const path = require("path");
const webpack = require("webpack");
module.exports = {
entry: "./src",
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].chunk.js"
},
module:{
rules: [
{
test: /\.html$/,
use: [{ loader: './plugin/templateLoader' }]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['env'],
plugins: [require("./plugin/myBabelPlugin")]
}
},
}
]
}
}
var acorn = require("acorn-dynamic-import").default;
function MyPlugin(options) {
// Configure your plugin with options...
}
MyPlugin.prototype.apply = function(compiler) {
compiler.plugin("compilation", function(compilation, data) {
data.normalModuleFactory.plugin(
"parser"
, function(parser, options) {
parser.plugin(
[
"statement if"
]
,(node)=>
Object.assign(
node
,{
test:{
type:"Literal",
start: node.test.start,
end: node.test.start+4,
loc: {
start: {
line: 7,
column: 3
},
end: {
line: 7,
column: node.test.loc.start.column+4
}
},
range: [
node.test.range,
node.test.range+4
],
value: true,
raw: "true"
}
}
)
);
});
});
};
module.exports = MyPlugin;
module.exports = function ({ types: t }) {
return {
visitor: {
IfStatement(path, file) {
path.node.test = {
"type": "BooleanLiteral",
"start": path.node.test.start,
"end": path.node.test.start+4,
"loc": {
"start": {
"line": 7,
"column": path.node.test.loc.start.column
},
"end": {
"line": 7,
"column": path.node.test.loc.start.column+4
}
},
"value": true
}
// debugger;
// path.unshiftContainer('body', t.expressionStatement(t.stringLiteral('use helloworld')));
}
}
};
};
const path = require("path");
const webpack = require("webpack");
module.exports = {
entry: "./src",
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].chunk.js"
},
module:{
rules: [
{
test: /\.html$/,
use: [{ loader: './plugin/templateLoader' }]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['env'],
plugins: [require("./plugin/myBabelPlugin")]
}
},
}
]
}
}