Webpack 4封闭问题与共享包

时间:2018-05-09 22:58:35

标签: javascript webpack webpack-4

我试图从3升级到Webpack 4,并且遇到共享捆绑关闭的问题。

我的网址设置为创建shared.js文件,在a.jsb.js之间共享我的代码。特别是,在shared.js包中,有一个带有store变量的索引文件。我们只导出一个名为getStore()的函数,它返回storegetStore的{​​{1}}号调用发生在a.jsb.js个文件的不同位置。

我们页面上的脚本阵容如下所示:

/** some html **/
<script src=""/scripts/shared.js""></script>
<script src=""/scripts/a.js""></script>
<script src=""/scripts/b.js""></script>

在Webpack 3中,第一次从getStore()调用shared.js(即将来电)中的a.js代码时,会创建store的实例然后从store调用中调用返回getStore()。随后从getStore()调用a.js,它不再创建store的实例,而是从getStore()返回相同的值。然后在a.js完成并b.js运行后,当b.js调用getStore()时,它不会实例化store,而是使用与a.js相同的实例用过的。在这种情况下,store与[{1}}和a.js之间的实例相同。

但是在Webpack 4中,行为有所不同。当b.js调用a.js中的代码时,当代码首次引用shared.js时,与之前类似,它将创建getStore()的新实例,而store运行并调用a.js它返回相同的实例。但是,当getStore()初始引用b.js代码时,它不会使用相同的shared.js实例,而是会在a.js内创建store的新实例。 {1}}脚本运行,在调用b.js时引用第二个store。在这种情况下,有两个getStore()个实例,每个实例对storea.js都是唯一的。

不确定Webpack 4中导致此问题的不同之处。我们在Webpack 3中使用b.js切换,现在使用内置的优化设置。以下是它们的配置方式。

WEBPACK 3:

CommonChunksPlugin

WEBPACK 4:

plugins: [..., new webpack.optimize.CommonsChunkPlugin({
    name: 'shared',
    filename: '[name].js',
    minChunks: 2
})]

两个Webpack配置都吐出大致相同大小的文件,在调试和查看调用堆栈时,optimization: { splitChunks: { cacheGroups: { shared: { name: 'shared', chunks: 'initial', minChunks: 2 } } } } 的调用来自相应的a / b.js文件。

是否有解释为什么getStore()a.js获取Webpack 4中b.js shared.js对象的单独实例与获取与Webpack 3中相同实例的实例?当脚本相互依赖时,它们的闭包/作用域应如何处理共享代码?

1 个答案:

答案 0 :(得分:1)

Idk,如果您知道的话,但我想分享我的发现。

TL; DR:拆分块在每个调用它的库的公共块中实例化该模块的新实例。

从乞求开始,您的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
        }
    },

快速注释,常见的块将添加到webpackJsonp下的窗口中。如果在浏览器的控制台中输入window.webpackJsonp[0][1],将会看到一个具有数字键且值是函数的对象。

这里的关键部分是,webpack基本上像这样在公共块中实例化每个模块。因此,每个库都将在通用块中拥有自己的模块版本。