从Webpack 1.x迁移到2.x.

jAn*_*ndy 17 javascript webpack webpack-2

在Webpack 1.x中我经常做以下事情:

require.ensure([ './mod2.js' ], ( require ) => {
    setTimeout(() => {
        // some later point in time, most likely through any kind of event
        var data = require( './mod2.js' ); // actual evaluating the code
    },1100);
}, 'myModule2');
Run Code Online (Sandbox Code Playgroud)

通过这种技术,我们能够通过网络传输webpack-bundle,但在稍后的某个时间点评估该bundle的实际内容(JavaScript代码).此外,使用require.ensure我们可以命名捆绑包,在本例中为myModule2,因此我们可以在捆绑发生执行webpack时看到名称/别名.

在Webpack 2.x中,新的方法是使用System.import.虽然我现在喜欢收到Promise对象,但我有两个问题.上面代码的等价物如下所示:

System.import( './mod2.js' ).then( MOD2 => {
    // bundle was transferred AND evaluated at this point   
});
Run Code Online (Sandbox Code Playgroud)
  • 我们现在如何分割转移和评估?
  • 我们怎样才能命名捆绑包?

Github上的Webpack文档说明如下:

完全动态需要现在默认失败

仅具有表达式(即require(expr))的依赖项现在将创建空上下文而不是完整目录的上下文.

最好的重构此代码,因为它不适用于ES6模块.如果这不可能,您可以使用ContextReplacementPlugin来提示编译器正确解析.

我不确定这在这种情况下是否起作用.他们还谈到代码分裂,但它很简单,他们没有提到任何"问题"或如何解决.

ssu*_*ube 5

tl; dr: System.resolveSystem.register做你想要的大部分.这个答案的其余部分是为什么require.ensure不能以及如何System.import称呼其他人.

认为 ES6模块可以防止它运行良好,虽然通过相关规范遵循它是棘手的,所以我可能完全错了.

那就是说,让我们从一些参考文献开始:

  1. WHATWG模块加载
  2. 关于模块ES6规范(§15.2)
  3. 所述CommonJS的模块规范
  4. 关于ES6模块精彩2条文章

第一个参考文献解释了更多的行为,虽然我不完全确定它是如何规范化的.后者解释了JS方面的实现细节.由于没有平台实现这一点,我没有参考它在现实生活中的实际工作方式,我们将不得不依赖规范.

require已提供的的WebPack 1.x中是CommonJS的和AMD的混搭需要.其中的CommonJS方面在ref#3中描述,特别是"模块上下文"部分.没有提到require.ensure,AMD的"规范"(例如它)也没有,所以这纯粹是webpack的发明.也就是说,这个特征从来都不是真实的,在官方和幻想中被指定的意义上.

也就是说,我认为require.ensure与ES6模块存在冲突.调用System.import应该从对象调用该import方法.参考文献#2中的相关部分没有明确说明,但§10.1确实提到了将加载器附加到.LoaderSystem

Loader.prototype.import方法并不十分牵扯,第4步是唯一让我们感兴趣的方法:

  1. 返回使用履行处理程序转换Resolve(loader,name,referrer)的结果,当使用参数键调用时,运行以下步骤:
    1. 让entry为EnsureRegistered(loader,key).
    2. 返回使用履行处理程序转换LoadModule(entry,"instantiate")的结果,该处理程序在调用时运行以下步骤:
      1. 返回EnsureEvaluated(条目).

流程是resolve-register-load-evaluate,您希望在加载和评估之间中断.但是请注意,负载阶段要求LoadModulestage设置为"instantiate".这意味着并且可能要求模块已经被翻译RequestTranslate过来,它在尝试查找模块的入口点等时进行了大量的重度解析.

从它的声音来看,这已经做了比你想要的更多的工作.由于模块加载的基础知识需要一个已知的入口点,我认为没有办法避免解析和部分评估模块与暴露的调用System.你已经知道了.

问题是System.import在解析之前不可能知道模块是否是必须要评估的ES6模块或者是否可以推迟的webpack包.必须进行解析以确定我们是否需要解析,从而导致鸡与蛋的问题.

到现在为止,我们一直在关注从路径System.import通过Loader.import假设您想要完成整个端到端的加载过程,那么这个调用正在决定我们所处的导入阶段.底层调用,例如Loader.prototype.load,提供对这些阶段的细粒度控制.

我不确定你将如何调用前两个阶段(获取和翻译),但如果你能够翻译和注册一个模块,以后的调用应该简单地评估并返回它.

如果规范是准确的,那么这应该通过System.loader属性公开(在支持实现中)并且将具有您需要调用的方法.您无法访问流的大部分内容,因此我建议不要这样做,而是设置代码,以便在加载模块时没有重要的运行.如果这是不可能的,您需要通过注册重新创建流程,但不要羞于评估.