最终修改
tl; dr解决这个问题是不可能的。虽然下面的最佳答案确实有一些很好的信息。
从contacts.js
开始考虑以下代码。这是一个动态加载的模块,在代码中的其他位置System.import
按需加载。
如果SharedUtil1
也用于动态加载了System.import
的其他模块,我将如何排除SharedUtility1
排除< / strong>来自所有这些模块,并且仅按需加载第一次需要它?
System.import
的顶级SharedUtil1
无法正常工作,因为我的导出依赖于它:导出只能放在模块代码的顶层,没有任何形式的回调。
Webpack可以实现吗?我是2.0.7版本。
import SharedUtil1 from '../../SharedUtilities/SharedUtility1';
class Contacts{
constructor(data){
this.data = data;
this.sharedUtil1 = new SharedUtil1();
}
}
export default Contacts;
更新1
我认为bundle loader是我想要的,但不是,这会将您导入的模块转换为一个不同的函数,一旦它完成异步加载,您就可以使用回调来调用实际模块。这意味着您无法透明地使模块X异步加载,而无需对代码进行重大更改,更不用说您回到最初描述的问题,如果您的顶级模块依赖于现在异步加载的依赖项,无法导出它,因为导出必须位于顶层。
Webpack中是否没有办法表示如果需要按需加载依赖关系X,并且有任何导入的模块导入它以透明地等待导入过程?我认为这个用例对于任何远程大型应用程序都是 sine qua non ,因此我不得不认为我只是遗漏了一些东西。
更新2
Per Peter的回答,我试图让重复数据删除工作,因为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代码仍然放在联系人和任务包中。
答案 0 :(得分:15)
阅读完博客文章后,我终于明白了你的意图。我对#34;顶级依赖关系&#34;。
这个词感到有些困惑您有两个模块(async-a
和async-b
),它们可以从任何地方按需加载(此处为模块main
),并且两者都有共享模块的引用({{ 1}})。
shared
默认情况下,webpack会创建一个这样的块树:
- - -> on-demand-loading (i. e. System.import)
---> sync loading (i. e. import)
main - - -> async-a ---> shared
main - - -> async-b ---> shared
---> 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]
&lt; { shared
或同一用户使用async-a/b
和async-a
的概率很低。它是默认值,因为它是最简单的行为,可能是您所期望的:一个async-b
=&gt;一块。在我看来,它也是最常见的情况。
但如果System.import
&gt; = 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
请记住,CommonsChunkPlugin有一个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)
选项来定义模块何时被线程化为minChunks
(随意提供一个自定义函数来选择模块)。
以下是一个详细说明设置和输出的示例:https://github.com/webpack/webpack/tree/master/examples/extra-async-chunk
另一个配置更多:https://github.com/webpack/webpack/tree/master/examples/extra-async-chunk-advanced
答案 1 :(得分:11)
如果我已经正确理解了您,那么当不同的代码块将其声明为依赖项时,您希望防止多次加载相同的依赖项。
是的,这是可能的;如何操作取决于应用程序中的上下文以及它是在ES6还是ES5中。
Webpack 1是在ECMA Script 5中构建的,通常使用CommonJS或RequireJS语法进行模块导出和导入。使用此语法时,可以使用以下功能来防止重复代码:
如果您使用一些具有很酷依赖树的库,则可能会发生 有些文件是相同的。 Webpack可以找到这些文件和 重复删除它们。这可以防止包含重复的代码 您的捆绑包,而是在运行时应用该函数的副本。的它 不会影响语义。
强调是我的,而不是来源
如文档所述,代码拆分保持不变;需要sharedUtil1
的每个模块都应该正常声明require
。为了防止多次加载相同的依赖项,启用了webpack设置,使webpack在运行时包含它们之前显式检查文件是否有重复。
此选项已启用
--optimize-dedupe
resp。 new webpack.optimize.DedupePlugin()
require.ensure
函数接受另外的第3个参数。这个 必须是一个字符串。如果两个分割点传递相同的字符串,则使用 相同的块... 如果模块位于多个子块中,require.include
可能很有用。 父级中的require.include
将包括模块和 子块中模块的实例将消失。
简而言之,模块的加载会延迟到编译后期。这允许在包含重复定义之前将其删除。文档提供了示例。
CommonsChunkPlugin
可以移动多个条目中出现的模块 块到一个新的入口块(公共块)。运行时被移动 公共块也是。这意味着旧的条目块是初始的 现在大块。
这非常特定于多个页面之间共享块,在其他情况下无关紧要。
支持高级模块导入功能......正在进行中。要了解事物的位置,请参阅以下链接:
以下是ES6模块和webpack的一个很好的总结:ES6 Modules with TypeScript and Webpack
以上信息很可能会过时。
为了你自己的理智,我建议:
如果优化很重要: 当Webpack 2稳定并发布时,恢复为CommonJS / RequireJS语法并升级到ECMA Script 6。
如果 ECMA Script 6语法很重要: 使用标准的ECMA Script 6导入导出格式,并在可用时添加优化功能。
尝试在sill不稳定的webpack中使用高级模块加载功能有太多的变化2.等待事情稳定下来,一些非常好的插件在尝试之前变得可用。
答案 2 :(得分:1)
答案 3 :(得分:0)
System.import
。 Webpack现在支持import()
,这需要使用polyfill进行承诺。