是否可以让 webpacks System.import 使用 ajax(用于进度事件)?

Fli*_*ion 4 javascript ajax progress-bar webpack webpack-2

所以我刚刚更新到 webpack 2 并进行了我的第一个工作设置,其中 webpack 通过查看 System.import 调用自动创建块。好甜!

但是,我使用 ajax 调用加载初始块,以便在加载时显示进度

所以我的问题是,我可以以某种方式覆盖或更改 System.import 的功能,以便它使用我可以侦听事件的 ajax 请求,而不是用<script>标签加载块吗?

Joh*_*ald 5

不,不幸的是没有。webpack 2 转换System.import()require.ensure()只使用<script>标签的普通调用。甚至官方的WHATWG Loader Spec也没有为这种事件提供 API。我为这个问题创建了一个问题。

关于 webpack:有一种方法可以实现您自己的require.ensure(). 但是,由于块加载是 webpack 不可或缺的一部分,因此需要更深入地研究。我不确定这对你来说有多重要,但你可能对 webpack 内部的工作方式感兴趣,所以让我们来看看:

在 webpack 中,所有内部功能都作为插件实现。这样,webpack 就能够支持许多不同的特性和环境。因此,如果您对 webpack 中的实现方式感兴趣,那么 a) 查看WebpackOptionsApply或 b) 搜索特定的字符串/代码片段总是一个好主意。

块加载在很大程度上取决于给定的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
};
Run Code Online (Sandbox Code Playgroud)

如果您查看每个插件,您会发现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")
    );
}
Run Code Online (Sandbox Code Playgroud)

我们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());
    });
};
Run Code Online (Sandbox Code Playgroud)

也许,您也可以重复使用JsonpChunkTemplatePluginJsonpHotUpdateChunkTemplatePlugin插件,但这取决于您的用例/实现。

XHRMainTemplatePlugin现在可能看起来像这样:

function XHRMainTemplatePlugin() {}

XHRMainTemplatePlugin.prototype.apply = function (mainTemplate) {
    mainTemplate.plugin("require-ensure", function(_, chunk, hash) {
        return this.asString([
            // Add your custom implementation here
            "fetch()"
        ]);
    });
};
Run Code Online (Sandbox Code Playgroud)

我不会在这里继续下去,因为我认为这个答案已经足够长了。但我建议创建一个真正的小示例项目并检查 webpack 创建的输出。内部的 webpack 插件乍一看可能有点吓人,但它们中的大多数都很短,只做一件事。你也可以从他们那里得到一些启发。