[英]Webpack 2 - Code splitting top-level dependencies
最终编辑
tl; dr决议这是不可能的。
虽然下面的最佳答案确实有一些很好的信息。
从contacts.js
考虑下面的代码。 这是一个动态加载的模块,在代码中的其他地方使用System.import
按需加载。
如果SharedUtil1
也被用于在其中也动态加载与其它模块System.import
,我将如何去了解有SharedUtility1
所有这些模块的排除 ,只有按需加载第一次它的需要?
SharedUtil1
顶级System.import
将无法工作,因为我的导出依赖于它:导出只能放在模块代码的顶层,而不能放在任何类型的回调中。
Webpack可以实现吗? 我的版本是2.0.7测试版。
import SharedUtil1 from '../../SharedUtilities/SharedUtility1';
class Contacts{
constructor(data){
this.data = data;
this.sharedUtil1 = new SharedUtil1();
}
}
export default Contacts;
更新1
我认为捆绑加载器是我想要的,但是没有,它将你导入的模块转换为一个不同的函数,一旦它完成异步加载,你就可以通过回调来访问实际的模块。 这意味着你不能透明地使模块X异步加载而不对代码进行重大更改,更不用说你回到最初描述的问题,如果你的顶级模块依赖于现在的异步加载依赖,没有办法导出它,因为导出必须在顶层。
Webpack中是否有办法表示依赖加载依赖关系X(如果需要),并且有任何导入模块导入它以透明地等待导入过程? 我认为这个用例对于任何远程大型应用程序都是必不可少的 ,所以我不得不认为我只是遗漏了一些东西。
更新2
根据彼得的回答,我试图让重复数据删除工作,因为commonChunk插件与端点之间共享代码有关,正如他所提到的,并且由于require.ensure
将加载的代码放入回调中,从而阻止您从ES6 export
任何代码取决于它。
就重复数据删除而言, contacts.js
和tasks.js
都像这样加载相同的sharedUtil
import SharedUtil1 from '../../sharedUtilities/sharedUtility1';
我试过运行webpack
webpack --optimize-dedupe
并且还通过添加
plugins: [
new webpack.optimize.DedupePlugin()
]
到webpack.config。 在这两种情况下,虽然sharedUtil代码仍然放在联系人和任务包中。
阅读完博客文章后,我终于明白了你的意图。 我对“顶级依赖”这个词感到有些困惑。
您有两个模块( async-a
和async-b
),它们可以从任何地方(这里是模块main
)按需加载,并且都有共享模块的引用( shared
)。
- - -> on-demand-loading (i. e. System.import)
---> sync loading (i. e. import)
main - - -> async-a ---> shared
main - - -> async-b ---> shared
默认情况下,webpack会创建一个这样的块树:
---> chunk uses other chunk (child-parent-relationship)
entry chunk [main] ---> on-demand chunk 1 [async-a, shared]
entry chunk [main] ---> on-demand chunk 2 [async-b, shared]
当shared
< async-a/b
或同一用户使用async-a
和async-b
的概率很低时,这很好。 这是默认值,因为它是最简单的行为,可能是您所期望的:一个System.import
=>一个块。 在我看来,这也是最常见的情况。
但是如果shared
> = async-a/b
并且用户加载async-a
和async-b
的概率很高,则有一个更有效的分块选项:(有点难以可视化):
entry chunk [main] ---> on-demand chunk 1 [async-a]
entry chunk [main] ---> on-demand chunk 2 [async-b]
entry chunk [main] ---> on-demand chunk 3 [shared]
When main requests async-a: chunk 1 and 3 is loaded in parallel
When main requests async-b: chunk 2 and 3 is loaded in parallel
(chunks are only loaded if not already loaded)
这不是默认行为,但有一个插件可以将其归档:异步模式下的CommonChunkPlugin
。 它在一堆块中找到公共/共享模块,并创建一个包含共享模块的新块。 在异步模式下,它会将新块与原始(但现在更小)的块并行加载。
new CommonsChunkPlugin({
async: true
})
// This does: (pseudo code)
foreach chunk in application.chunks
var shared = getSharedModules(chunks: chunk.children, options)
if shared.length > 0
var commonsChunk = new Chunk(modules: shared, parent: chunk)
foreach child in chunk.children where child.containsAny(shared)
child.removeAll(shared)
foreach dependency in chunk.getAsyncDepenendenciesTo(child)
dependeny.addChunk(commonsChunk)
请记住,CommonsChunkPlugin有一个minChunks
选项来定义模块何时作为shared
线程化(随意提供一个自定义函数来选择模块)。
下面是一个详细说明设置和输出的示例: https : //github.com/webpack/webpack/tree/master/examples/extra-async-chunk
另一个配置更多: https : //github.com/webpack/webpack/tree/master/examples/extra-async-chunk-advanced
如果我已经正确理解了您,那么当不同的代码块将其声明为依赖项时,您希望防止多次加载相同的依赖项。
是的,这是可能的; 如何做到这取决于您的应用程序中的上下文以及它是在ES6还是ES5中。
Webpack 1是在ECMA Script 5中构建的,通常使用CommonJS或RequireJS语法进行模块导出和导入。 使用此语法时,可以使用以下功能来防止重复的代码:
从webpack文档 :
如果您使用一些具有很酷依赖树的库,则可能会出现某些文件相同的情况。 Webpack可以找到这些文件并对其进行重复数据删除。 这可以防止在包中包含重复的代码,而是在运行时应用该函数的副本。 它不会影响语义。
重点是我的,而不是来源
如文档所述,代码拆分保持不变; 需要sharedUtil1
每个模块sharedUtil1
应该将require
声明为正常。 为了防止多次加载相同的依赖项,启用了webpack设置,该设置使webpack在运行时包含它们之前显式检查文件是否有重复。
使用--optimize-dedupe
resp启用此选项。 new webpack.optimize.DedupePlugin()
从webpack文档 :
require.ensure
函数接受另外的第3个参数。 这必须是一个字符串。 如果两个分割点传递相同的字符串,则它们使用相同的块...如果模块位于多个子块中,则require.include
可能很有用。 父require.include
中的require.include
将包含模块,子块中的模块实例将消失。
简而言之,模块的加载被延迟到编译后期。 这允许在包含重复定义之前将其删除。 该文档提供了示例。
从webpack文档 :
CommonsChunkPlugin
可以将多个条目块中出现的模块移动到新的条目块(公共块)。 运行时也会移动到commons块。 这意味着旧的条目块现在是初始块。
这非常特定于在多个页面之间共享块,这在其他情况下是不相关的。
对高级模块导入功能的支持是......正在进行的工作。 要了解事物的位置,请参阅以下链接:
以下是ES6模块和webpack的一个很好的总结: 带有TypeScript和Webpack的ES6模块
以上信息很可能会过时。
为了你自己的理智,我建议:
如果优化很重要 :当Webpack 2稳定并发布时,恢复为CommonJS / RequireJS语法并升级到ECMA Script 6。
如果ECMA Script 6语法很重要 :使用标准ECMA Script 6导入导出格式并在可用时添加优化功能。
尝试在sill不稳定的webpack中使用高级模块加载功能有太多的变化2.等待事情稳定下来,一些非常好的插件在尝试之前变得可用。
System.import
已在Webpack中弃用。 Webpack现在支持import()
,这需要使用polyfill来实现承诺。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.