3

我正在尝试从 3 升级到 Webpack 4,并且在共享包的关闭时遇到问题。

我的 webpack 设置为创建一个在和shared.js之间共享我的代码的文件。特别是,在包中,有一个带有变量的索引文件。我们只导出一个名为 的函数,它返回. 这种呼吁发生在我们和文件的不同地方。a.jsb.jsshared.jsstoregetStore()storegetStorea.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()中的代码时,它会创建一个实例,然后调用从调用返回。对from 的任何后续调用,它不再创建 的实例,而是从 . 返回相同的值。然后在完成并运行之后,当调用时,它不会实例化,而是使用与使用相同的实例。在这种情况下,麻烦和是相同的实例。shared.jsa.jsstorestoregetStore()getStore()a.jsstoregetStore()a.jsb.jsb.jsgetStore()storea.jsstorea.jsb.js

但是在 Webpack 4 中,行为有所不同。当a.js调用 中的代码时shared.js,当代码第一次引用 时getStore(),和之前类似,它会创建一个新的 实例store,并且在a.js运行和调用getStore()时返回相同的实例。但是,当b.js对代码进行初始引用时shared.js,它不会使用相同的实例a.js,而是创建一个新实例,store并且在整个b.js脚本运行过程中,它会store在调用getStore(). 在这种情况下,有 的两个实例,每个实例对于和store都是唯一的。a.jsb.js

不确定导致此问题的 Webpack 4 有什么不同。我们从使用CommonChunksPluginWebpack 3 切换到现在使用内置的优化设置。以下是它们的配置方式。

网页包 3:

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

网页包 4:

optimization: {
    splitChunks: {
        cacheGroups: {
            shared: {
                name: 'shared',
                chunks: 'initial',
                minChunks: 2
            }
        }
    }
}

两种 Webpack 配置都输出大致相同大小的文件,在调试和查看调用堆栈时,调用getStore()来自各自的 a/b.js 文件。

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

4

1 回答 1

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 本质上将每个模块实例化为这样的公共块。因此,每个库都会在公共块中拥有自己的模块版本。

于 2019-10-25T01:00:42.100 回答