从 Webpack 1.x 迁移到 2.x
Migrating from Webpack 1.x to 2.x
在 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[=34] 时看到名称/别名=].
在 Webpack 2.x 中,新的方法是使用 System.import
。虽然我现在喜欢接收 Promise 对象,但我对这种风格有两个问题。上面代码的等价物如下所示:
System.import( './mod2.js' ).then( MOD2 => {
// bundle was transferred AND evaluated at this point
});
- 现在怎么拆分转账和评价?
- 我们如何命名捆绑包?
Github 上的 Webpack documentation 表示如下:
Full dynamic requires now fail by default
A dependency with only an expression (i. e. require(expr)) will now
create an empty context instead of an context of the complete
directory.
Best refactor this code as it won't work with ES6 Modules. If this is
not possible you can use the ContextReplacementPlugin to hint the
compiler to the correct resolving.
我不确定这在本案中是否起作用。他们还在其中讨论了代码拆分,但非常简短,他们没有提到任何 "issues" 或如何解决。
tl;dr: System.resolve
and System.register
做你想做的大部分事情。这个答案的其余部分是为什么 require.ensure
不能以及 System.import
如何调用其他人。
我认为 ES6 模块阻止了它的正常运行,尽管通过相关规范遵循它很棘手,所以我可能完全错了。
也就是说,让我们从一些参考开始:
- WhatWG module loader
- ES6 specification on modules (§15.2)
- CommonJS module specification
- fantastic 2ality article on ES6 modules
第一个参考解释了更多的行为,尽管我不完全确定它是如何规范化的。后者解释了JS端的实现细节。由于还没有平台实现这一点,我没有关于它在现实生活中如何实际工作的参考,我们将不得不依赖规范。
The require
that has been available in webpack 1.x 是 CommonJS 和 AMD 要求的混搭。 CommonJS 方面在参考#3 中有描述,特别是 "Module Context" 部分。那里没有提到 require.ensure
,也没有提到 AMD "specification"(实际上是这样),所以这纯粹是 webpack 的发明。也就是说,该功能从来都不是真实的,因为它被指定在某个官方的地方并且看起来很花哨。
也就是说,我认为 require.ensure
与 ES6 模块冲突。调用 System.import
应该调用 import
method from a Loader
object. The relevant section in ref#2 does not lay that out explicitly, but §10.1 确实提到将加载程序附加到 System
。
Loader.prototype.import
method 并不十分复杂,我们只对第 4 步感兴趣:
- Return the result of transforming Resolve(loader, name, referrer) with a fulfillment handler that, when called with argument key, runs the following steps:
- Let entry be EnsureRegistered(loader, key).
- Return the result of transforming LoadModule(entry, "instantiate") with a fulfillment handler that, when called, runs the following steps:
- Return EnsureEvaluated(entry).
流程是解析-注册-加载-评估,您想要在加载和评估之间中断。但是请注意,加载阶段调用 LoadModule
with stage
set to "instantiate"
. That implies and probably requires the module has already been translated via RequestTranslate
,它会在尝试查找模块的入口点等时执行大量繁重的解析。
从它的声音来看,这已经完成了比你想要的更多的工作。由于模块加载的基础知识需要一个已知的入口点,我认为没有办法避免使用从 System
公开的调用来解析和部分评估模块。你已经知道了。
问题是 System.import
不可能知道——直到解析之后——模块是必须评估的 ES6 模块还是可以延迟的 webpack 包。解析必须要搞清楚是否需要解析,导致先有鸡还是先有蛋的问题。
到目前为止,我们一直在沿着从 System.import
到 Loader
的路径前进。 import
调用指示我们所处的导入阶段,假设您想要完成完整的端到端加载过程。底层调用,如 Loader.prototype.load
,提供对这些阶段的细粒度控制。
我不确定您将如何调用前两个阶段(获取和翻译),但如果您能够翻译和注册模块,则以后的调用应该简单地评估并 return 它。
如果规范准确无误,这应该通过 System.loader
属性 公开(在支持实现中)并且会有您需要调用的方法。您无权访问大部分流程,因此我建议您不要这样做,而是设置您的代码,以便在加载模块时不会运行任何重要内容。如果那不可能,您需要通过注册重新创建流程,但不要回避评估。
在 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[=34] 时看到名称/别名=].
在 Webpack 2.x 中,新的方法是使用 System.import
。虽然我现在喜欢接收 Promise 对象,但我对这种风格有两个问题。上面代码的等价物如下所示:
System.import( './mod2.js' ).then( MOD2 => {
// bundle was transferred AND evaluated at this point
});
- 现在怎么拆分转账和评价?
- 我们如何命名捆绑包?
Github 上的 Webpack documentation 表示如下:
Full dynamic requires now fail by default
A dependency with only an expression (i. e. require(expr)) will now create an empty context instead of an context of the complete directory.
Best refactor this code as it won't work with ES6 Modules. If this is not possible you can use the ContextReplacementPlugin to hint the compiler to the correct resolving.
我不确定这在本案中是否起作用。他们还在其中讨论了代码拆分,但非常简短,他们没有提到任何 "issues" 或如何解决。
tl;dr: System.resolve
and System.register
做你想做的大部分事情。这个答案的其余部分是为什么 require.ensure
不能以及 System.import
如何调用其他人。
我认为 ES6 模块阻止了它的正常运行,尽管通过相关规范遵循它很棘手,所以我可能完全错了。
也就是说,让我们从一些参考开始:
- WhatWG module loader
- ES6 specification on modules (§15.2)
- CommonJS module specification
- fantastic 2ality article on ES6 modules
第一个参考解释了更多的行为,尽管我不完全确定它是如何规范化的。后者解释了JS端的实现细节。由于还没有平台实现这一点,我没有关于它在现实生活中如何实际工作的参考,我们将不得不依赖规范。
The require
that has been available in webpack 1.x 是 CommonJS 和 AMD 要求的混搭。 CommonJS 方面在参考#3 中有描述,特别是 "Module Context" 部分。那里没有提到 require.ensure
,也没有提到 AMD "specification"(实际上是这样),所以这纯粹是 webpack 的发明。也就是说,该功能从来都不是真实的,因为它被指定在某个官方的地方并且看起来很花哨。
也就是说,我认为 require.ensure
与 ES6 模块冲突。调用 System.import
应该调用 import
method from a Loader
object. The relevant section in ref#2 does not lay that out explicitly, but §10.1 确实提到将加载程序附加到 System
。
Loader.prototype.import
method 并不十分复杂,我们只对第 4 步感兴趣:
- Return the result of transforming Resolve(loader, name, referrer) with a fulfillment handler that, when called with argument key, runs the following steps:
- Let entry be EnsureRegistered(loader, key).
- Return the result of transforming LoadModule(entry, "instantiate") with a fulfillment handler that, when called, runs the following steps:
- Return EnsureEvaluated(entry).
流程是解析-注册-加载-评估,您想要在加载和评估之间中断。但是请注意,加载阶段调用 LoadModule
with stage
set to "instantiate"
. That implies and probably requires the module has already been translated via RequestTranslate
,它会在尝试查找模块的入口点等时执行大量繁重的解析。
从它的声音来看,这已经完成了比你想要的更多的工作。由于模块加载的基础知识需要一个已知的入口点,我认为没有办法避免使用从 System
公开的调用来解析和部分评估模块。你已经知道了。
问题是 System.import
不可能知道——直到解析之后——模块是必须评估的 ES6 模块还是可以延迟的 webpack 包。解析必须要搞清楚是否需要解析,导致先有鸡还是先有蛋的问题。
到目前为止,我们一直在沿着从 System.import
到 Loader
的路径前进。 import
调用指示我们所处的导入阶段,假设您想要完成完整的端到端加载过程。底层调用,如 Loader.prototype.load
,提供对这些阶段的细粒度控制。
我不确定您将如何调用前两个阶段(获取和翻译),但如果您能够翻译和注册模块,则以后的调用应该简单地评估并 return 它。
如果规范准确无误,这应该通过 System.loader
属性 公开(在支持实现中)并且会有您需要调用的方法。您无权访问大部分流程,因此我建议您不要这样做,而是设置您的代码,以便在加载模块时不会运行任何重要内容。如果那不可能,您需要通过注册重新创建流程,但不要回避评估。