是否可以让 webpacks System.import 使用 ajax (用于进度事件)?
Is it possible to let webpacks System.import use ajax (for progress events)?
所以我刚刚更新到 webpack 2 并有了我的第一个工作设置,其中 webpack 通过查看 System.import 调用自动创建块。好甜!
但是,我使用 ajax 调用加载了初始块,这样我就可以 show the progress while loading
所以我的问题是,我能否以某种方式覆盖或更改 System.import 的功能,以便它使用我可以监听事件的 ajax 请求,而不是加载块<script>
标签?
不,不幸的是没有。 webpack 2 将 System.import()
转换为仅使用 <script>
标签的普通 require.ensure()
调用。连这个问题的官方WHATWG Loader Spec does not provide an API for this kind of event. I've created an issue
关于 webpack:有一种方法可以实现您自己的 require.ensure()
。然而,由于块加载是 webpack 不可或缺的一部分,这需要更深入地研究。我不确定这对你有多重要,但你可能对 webpack 内部的工作方式感兴趣,所以让我们来看看:
在 webpack 中,所有内部功能都作为插件实现。这样,webpack 就能够支持很多不同的特性和环境。因此,如果您对 webpack 中的实现方式感兴趣,a) 查看 WebpackOptionsApply
或 b) 搜索特定的 string/code 片段总是一个好主意。
块加载在很大程度上取决于给定的 target
,因为您需要针对每个环境进行不同的实现。 Webpack 允许您定义自定义目标。当您传入函数而不是字符串时,webpack 会使用 compiler
实例调用该函数。您可以在那里应用所有必需的插件。由于我们的自定义目标几乎类似于 web
目标,因此我们只需复制 web
目标中的所有内容:
// webpack.config.js
const NodeSourcePlugin = require("webpack/lib/node/NodeSourcePlugin");
const FunctionModulePlugin = require("webpack/lib/FunctionModulePlugin");
const LoaderTargetPlugin = require("webpack/lib/LoaderTargetPlugin");
const JsonpChunkTemplatePlugin = require("webpack/lib/JsonpChunkTemplatePlugin");
const JsonpHotUpdateChunkTemplatePlugin = require("webpack/lib/JsonpHotUpdateChunkTemplatePlugin");
function customTarget(compiler) {
compiler.apply(
new JsonpTemplatePlugin(compiler.options.output),
new FunctionModulePlugin(compiler.options.output),
new NodeSourcePlugin(compiler.options.node),
new LoaderTargetPlugin("web")
);
}
module.exports = {
entry: require.resolve("./app/main.js"),
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
},
target: customTarget
};
如果您查看每个插件,您会发现 JsonpTemplatePlugin
负责加载块。因此,让我们用自己的实现替换它。我们称之为 XHRTemplatePlugin
:
function customTarget(compiler) {
compiler.apply(
new XHRTemplatePlugin(compiler.options.output),
new FunctionModulePlugin(compiler.options.output),
new NodeSourcePlugin(compiler.options.node),
new LoaderTargetPlugin("my-custom-target")
);
}
我们的XHRTemplatePlugin
负责提供主块中的代码,每个子块中的代码以及热更新:
function XHRTemplatePlugin() {}
XHRTemplatePlugin.prototype.apply = function (compiler) {
compiler.plugin("this-compilation", function(compilation) {
compilation.mainTemplate.apply(new XHRMainTemplatePlugin());
compilation.chunkTemplate.apply(new XHRChunkTemplatePlugin());
compilation.hotUpdateChunkTemplate.apply(new XHRHotUpdateChunkTemplatePlugin());
});
};
或许,您也可以重复使用 JsonpChunkTemplatePlugin
和 JsonpHotUpdateChunkTemplatePlugin
插件,但这取决于您的 use-case/implementation.
您的 XHRMainTemplatePlugin
现在可能看起来像这样:
function XHRMainTemplatePlugin() {}
XHRMainTemplatePlugin.prototype.apply = function (mainTemplate) {
mainTemplate.plugin("require-ensure", function(_, chunk, hash) {
return this.asString([
// Add your custom implementation here
"fetch()"
]);
});
};
这里就不多说了,因为我觉得这个回答已经够长了。但我建议创建一个真正的小示例项目并检查 webpack 创建的输出。内部的 webpack 插件乍一看可能有点吓人,但它们中的大多数都很短而且只做一件事。你也可以从中得到一些启发。
所以我刚刚更新到 webpack 2 并有了我的第一个工作设置,其中 webpack 通过查看 System.import 调用自动创建块。好甜!
但是,我使用 ajax 调用加载了初始块,这样我就可以 show the progress while loading
所以我的问题是,我能否以某种方式覆盖或更改 System.import 的功能,以便它使用我可以监听事件的 ajax 请求,而不是加载块<script>
标签?
不,不幸的是没有。 webpack 2 将 System.import()
转换为仅使用 <script>
标签的普通 require.ensure()
调用。连这个问题的官方WHATWG Loader Spec does not provide an API for this kind of event. I've created an issue
关于 webpack:有一种方法可以实现您自己的 require.ensure()
。然而,由于块加载是 webpack 不可或缺的一部分,这需要更深入地研究。我不确定这对你有多重要,但你可能对 webpack 内部的工作方式感兴趣,所以让我们来看看:
在 webpack 中,所有内部功能都作为插件实现。这样,webpack 就能够支持很多不同的特性和环境。因此,如果您对 webpack 中的实现方式感兴趣,a) 查看 WebpackOptionsApply
或 b) 搜索特定的 string/code 片段总是一个好主意。
块加载在很大程度上取决于给定的 target
,因为您需要针对每个环境进行不同的实现。 Webpack 允许您定义自定义目标。当您传入函数而不是字符串时,webpack 会使用 compiler
实例调用该函数。您可以在那里应用所有必需的插件。由于我们的自定义目标几乎类似于 web
目标,因此我们只需复制 web
目标中的所有内容:
// webpack.config.js
const NodeSourcePlugin = require("webpack/lib/node/NodeSourcePlugin");
const FunctionModulePlugin = require("webpack/lib/FunctionModulePlugin");
const LoaderTargetPlugin = require("webpack/lib/LoaderTargetPlugin");
const JsonpChunkTemplatePlugin = require("webpack/lib/JsonpChunkTemplatePlugin");
const JsonpHotUpdateChunkTemplatePlugin = require("webpack/lib/JsonpHotUpdateChunkTemplatePlugin");
function customTarget(compiler) {
compiler.apply(
new JsonpTemplatePlugin(compiler.options.output),
new FunctionModulePlugin(compiler.options.output),
new NodeSourcePlugin(compiler.options.node),
new LoaderTargetPlugin("web")
);
}
module.exports = {
entry: require.resolve("./app/main.js"),
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
},
target: customTarget
};
如果您查看每个插件,您会发现 JsonpTemplatePlugin
负责加载块。因此,让我们用自己的实现替换它。我们称之为 XHRTemplatePlugin
:
function customTarget(compiler) {
compiler.apply(
new XHRTemplatePlugin(compiler.options.output),
new FunctionModulePlugin(compiler.options.output),
new NodeSourcePlugin(compiler.options.node),
new LoaderTargetPlugin("my-custom-target")
);
}
我们的XHRTemplatePlugin
负责提供主块中的代码,每个子块中的代码以及热更新:
function XHRTemplatePlugin() {}
XHRTemplatePlugin.prototype.apply = function (compiler) {
compiler.plugin("this-compilation", function(compilation) {
compilation.mainTemplate.apply(new XHRMainTemplatePlugin());
compilation.chunkTemplate.apply(new XHRChunkTemplatePlugin());
compilation.hotUpdateChunkTemplate.apply(new XHRHotUpdateChunkTemplatePlugin());
});
};
或许,您也可以重复使用 JsonpChunkTemplatePlugin
和 JsonpHotUpdateChunkTemplatePlugin
插件,但这取决于您的 use-case/implementation.
您的 XHRMainTemplatePlugin
现在可能看起来像这样:
function XHRMainTemplatePlugin() {}
XHRMainTemplatePlugin.prototype.apply = function (mainTemplate) {
mainTemplate.plugin("require-ensure", function(_, chunk, hash) {
return this.asString([
// Add your custom implementation here
"fetch()"
]);
});
};
这里就不多说了,因为我觉得这个回答已经够长了。但我建议创建一个真正的小示例项目并检查 webpack 创建的输出。内部的 webpack 插件乍一看可能有点吓人,但它们中的大多数都很短而且只做一件事。你也可以从中得到一些启发。