Require.ensure()非阻塞

jAn*_*ndy 19 javascript amd commonjs webpack

如果我们有webpack创建的不同bundle ,我们可以在以后的某个时间require.ensure动态传输和评估它,它通过jsonPadding和一些webpack js魔法发生.如果我们有

require.ensure([ ], ( require ) => {
    console.log('before...');
    var data = require( './myModule.js' );
    console.log('after...');
  }, 'myModule')
Run Code Online (Sandbox Code Playgroud)

"after..."完全转移和评估该模块时会遇到.如果碰巧是这个/模块非常大,包含图像,css等等,那么加载将几乎锁定浏览器,而webpack javascript代码解包了包含其所有组件的包.

问题:有没有办法"挂钩"那个require魔法?例如,对于以下内容进行回调将是一个梦想的场景:

  • 整个文件/块已转移
  • 图像[1]进行了评估
  • css [1]被评估/样式标签被注入
  • javascript被评估了

等等,假设我们传输的包含有大量数据.一般来说,让我很难有一个很好的选择来动态地异步传输整个bundle,但仍然必须以完全同步/阻塞的方式加载那个bundle.

jAn*_*ndy 2

我想我自己对这个话题感到困惑,所以我的问题可能不够精确,无法得到正确的回答。然而,我对整个“commonJS 动态模块加载”上下文的误解是,它require.ensure()只会通过网络传输模块代码(分别是webpack 创建的块)。之后,传输的基本上只是一个大的 ECMAscript 文件,只是位于浏览器中,已缓存但尚未评估。整个的评估仅发生在实际require()调用时。

话虽如此,如何解耦和评估Module / Chunk的各个部分完全取决于您。例如,就像我原来的问题一样,requires()一些CSS Files、一些Images和一些HTML中的模块,所有这些都在调用时异步传输require.ensure()。您以何种方式require()(并因此评估)这些部分完全取决于您,如果需要,您可以自己解耦这些调用。

例如,一个模块看起来像这样:

模块1.js

"use strict";
import { io } from 'socket.io-client';

document.getElementById( 'foo' ).addEventListener('click', ( event ) => {
    let partCSS = require( 'style/usable!./someCoolCSS.css' ),
        moarCSS = require( 'style/usable!./moarCoolCSS.css' ),
        tmpl    = require( './myTemplate.html' ),
        image1  = require( './foo.jpg' ),
        image2  = require( './bar.png' );
}, false);
Run Code Online (Sandbox Code Playgroud)

当然,当其他模块调用时,所有这些文件都已包含在传输到客户端的块中:

require.ensure([ 'Module1.js' ], ( require ) => {
}, 'Module1');
Run Code Online (Sandbox Code Playgroud)

这是我的困惑。所以现在,我们可以玩自己require()内部的电话了module1.js。如果我们确实需要这样的大量文件,我们甚至可以使用setTimeout/ setImmediaterun-away-timer 来解耦每个调用之间的同步评估require()(如果需要或想要)。

实际上是一个非常简单的故事的长答案。

TL;DR:require.ensure通过线路传输整个块。该块包含作为require()受保证模块内的调用一部分的所有文件。但是这些文件不会自动评估。只有当实际require()调用在运行时匹配时才会发生这种情况(此时由 webpackJSONP 调用表示)