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

时间:2016-10-28 23:47:52

标签: 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');

通过这种技术,我们能够通过网络传输 webpack-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   
});
  • 我们现在如何分割转移和评估?
  • 我们怎样才能命名捆绑包?

Github上的Webpack documentation说明如下:

  

默认情况下,完全动态需要失败

     

现在只有一个表达式(即,require(expr))的依赖项   创建一个空的上下文而不是完整的上下文   。目录

     

最佳重构此代码,因为它不能与ES6模块一起使用。如果是这样的话   不可能你可以使用ContextReplacementPlugin来提示   编译器正确解析。

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

1 个答案:

答案 0 :(得分:5)

tl; dr: System.resolveSystem.register完成您想要的大部分工作。这个答案的其余部分是require.ensure不能以及System.import如何调用其他人的原因。

认为 ES6模块阻止了这项工作,虽然遵循相关规范是很棘手的,所以我可能完全错了。

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

  1. WhatWG module loader
  2. ES6 specification on modules (§15.2)
  3. CommonJS module specification
  4. fantastic 2ality article on ES6 modules
  5. 第一个参考文献解释了更多的行为,尽管我并不完全确定它是如何规范化的。后者解释了JS方面的实现细节。由于没有平台实现这一点,我没有参考它在现实生活中的实际工作方式,我们将不得不依赖规范。

    webpack 1.x中的

    The require that has been available是CommonJS和AMD要求的mashup。其中的CommonJS方面在ref#3中描述,特别是“模块上下文”部分。没有提到require.ensure,AMD的“规范”(例如它)也没有,所以这纯粹是webpack的一项发明。也就是说,这个特征从来都不是真实的,因为它被指定为官方和花哨的地方。

    那就是说,我认为require.ensure与ES6模块冲突。致电System.import时,应从import method调用Loader object。参考文献2中的相关部分没有明确说明,但§10.1确实提到将加载器附加到System

    Loader.prototype.import method并非非常重要,第4步是唯一让我们感兴趣的人:

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

    流程是resolve-register-load-evaluate,您希望在load和evaluate之间中断。但请注意,加载阶段调用LoadModule并将stage设置为"instantiate"。这意味着并且可能要求模块已经通过RequestTranslate进行了翻译,Loader.prototype.load在尝试查找模块的入口点等时进行了大量的解析。

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

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

    到目前为止,我们一直在关注从System.importLoader的路径。假设您希望完成整个端到端加载过程,import调用将决定我们处于哪个导入阶段。底层调用,如{{3}},可以对这些阶段进行细粒度控制。

    我不确定你将如何调用前两个阶段(fetch和translate),但是如果你能够翻译和注册一个模块,以后的调用应该只是评估并返回它。

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