我正在尝试从3升级到Webpack 4,但遇到了一个共享包的关闭问题。
我的webpack创建了一个在a.js和b.js之间共享我的代码的shared.js文件。特别是,在shared.js包中,有一个带有store变量的索引文件。我们只导出一个名为getStore()的函数,该函数返回store。在a.js和b.js文件中,对getStore的调用发生在不同的位置。
我们页面上的脚本列表如下所示:
/** some html **/
<script src=""/scripts/shared.js""></script>
<script src=""/scripts/a.js""></script>
<script src=""/scripts/b.js""></script>在Webpack 3中,当第一次从a.js调用shared.js中的getStore()代码(调用传入)时,它创建了一个store实例,然后该实例的调用将从getStore()调用返回store。任何后续从a.js调用getStore()时,它都不再创建store的实例,而是从getStore()返回相同的值。然后,在a.js完成并运行b.js之后,当b.js调用getStore()时,它不会实例化store,而是使用与a.js相同的实例。在这种情况下,跨a.js和b.js的store是相同的实例。
然而,在《Webpack 4》中,这种行为有所不同。当a.js调用shared.js中的代码时,当代码第一次引用getStore()时,它将创建一个新的store实例,当a.js运行并调用getStore()时,它将返回相同的实例。但是,当b.js对shared.js代码进行初始引用时,它并不使用a.js所使用的相同实例,而是创建一个新的store实例,并且在整个b.js的脚本运行过程中,它在调用getStore()时引用第二个store。在这种情况下,有两个store实例,每个实例对于a.js和<代码>d45store>是唯一的。
我不确定在Webpack 4中是什么不同导致了这个问题。我们从使用Webpack 3中的CommonChunksPlugin切换到现在使用内置的优化设置。下面是它们的配置方式。
《WEBPACK 3》:
plugins: [..., new webpack.optimize.CommonsChunkPlugin({
name: 'shared',
filename: '[name].js',
minChunks: 2
})]WEBPACK 4:
optimization: {
splitChunks: {
cacheGroups: {
shared: {
name: 'shared',
chunks: 'initial',
minChunks: 2
}
}
}
}两个Webpack配置输出的文件大小大致相同,并且在调试和查看调用堆栈时,对getStore()的调用来自各自的a/b.js文件。
有没有解释为什么a.js和b.js在Webpack 4中获得了不同的shared.js store对象实例,而在Webpack 3中获得了相同的实例?当脚本相互依赖时,它们的闭包/作用域应该如何处理共享代码?
发布于 2019-10-25 09:00:42
如果你弄明白了,我很感谢,但我想分享我的发现。
TL;DR: Split chunk为调用它的每个库以公共块的形式实例化模块的新实例。
从请求开始,您的webpack库应该具有如下所示的函数。
var r = n(34);这将调用该库中检索模块的方法:
function n(t) {
if (n[t])
return n[t].exports;
var e = n[t] = {
i: t,
l: !1,
exports: {}
};
return s[t].call(e.exports, e, e.exports, o),
e.l = !0,
e.exports
}我找不到任何文档,但t是一个用于引用模块的数字(请记住这一点)。s是一个包含该库可以使用的所有模块的对象,而n是一个包含该库已经使用的所有模块的对象,本质上是对它们进行缓存。当n[t]不存在时,webpack会在n中添加一个通用对象,然后调用return s[t].call(e.exports, e, e.exports, o)。
假设t是34岁,webpack将调用以下方法
34: function(e, t, n) {
"use strict";
n.r(t);
var r = n(36);
t.default = function() {
var e = r.a.pageLevelOOM && r.a.adinfoOOMHeader
, t = r.a.pageLevelOOM && r.a.serverOOMHeader;
return r.a.adinfoOverride ? e : t
}
},Quick side note,common chunks将添加到webpackJsonp下的窗口中。如果在浏览器控制台中输入window.webpackJsonp[0][1],您将看到一个具有数字键和值的对象。
这里的关键部分是,webpack基本上在公共块中实例化了每个模块,如下所示。因此,每个库都会在公共块中拥有自己的模块版本。
https://stackoverflow.com/questions/50263198
复制相似问题