首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Webpack 4与共享捆绑包的闭包问题

问Webpack 4与共享捆绑包的闭包问题
EN

Stack Overflow用户
提问于 2018-05-10 06:58:35
回答 1查看 159关注 0票数 3

我正在尝试从3升级到Webpack 4,但遇到了一个共享包的关闭问题。

我的webpack创建了一个在a.js和b.js之间共享我的代码的shared.js文件。特别是,在shared.js包中,有一个带有store变量的索引文件。我们只导出一个名为getStore()的函数,该函数返回store。在a.js和b.js文件中,对getStore的调用发生在不同的位置。

我们页面上的脚本列表如下所示:

代码语言:javascript
复制
/** 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》:

代码语言:javascript
复制
plugins: [..., new webpack.optimize.CommonsChunkPlugin({
    name: 'shared',
    filename: '[name].js',
    minChunks: 2
})]

WEBPACK 4:

代码语言:javascript
复制
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中获得了相同的实例?当脚本相互依赖时,它们的闭包/作用域应该如何处理共享代码?

EN

回答 1

Stack Overflow用户

发布于 2019-10-25 09:00:42

如果你弄明白了,我很感谢,但我想分享我的发现。

TL;DR: Split chunk为调用它的每个库以公共块的形式实例化模块的新实例。

从请求开始,您的webpack库应该具有如下所示的函数。

代码语言:javascript
复制
var r = n(34);

这将调用该库中检索模块的方法:

代码语言:javascript
复制
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将调用以下方法

代码语言:javascript
复制
    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基本上在公共块中实例化了每个模块,如下所示。因此,每个库都会在公共块中拥有自己的模块版本。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50263198

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档