Проблемы закрытия Webpack 4 с общим пакетом

Я пытаюсь перейти на Webpack 4 с версии 3, и у меня возникают проблемы с закрытием общего пакета.

Мой веб-пакет настроен на создание файла shared.js, который делит мой код между a.js и b.js. В частности, в комплекте shared.js есть индексный файл с переменной store. Мы экспортируем только функцию с именем getStore(), которая возвращает store. Этот вызов getStore происходит в разных местах наших файлов a.js и b.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 является одним и тем же экземпляром для a.js и b.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.js и b.js.

Не уверен, что отличается в Webpack 4, что вызывает эту проблему. Мы отказались от использования CommonChunksPlugin в Webpack 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 и b.js получают отдельные экземпляры объекта shared.js store в Webpack 4, а не те же экземпляры, что и в Webpack 3? Когда сценарии полагаются друг на друга, как их замыкания/области действия должны обрабатывать общий код?


person mche    schedule 09.05.2018    source источник


Ответы (1)


Не знаю, разобрались ли вы, но я хотел бы поделиться своими выводами.

TL;DR: Разделить блок создает экземпляр нового экземпляра модуля в общих блоках для каждой вызывающей его библиотеки.

Начиная с самого начала, ваша библиотека веб-пакетов должна иметь функции, подобные приведенной ниже.

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] в консоли вашего браузера, вы увидите объект с числовыми ключами, а значения являются функциями.

Ключевым моментом здесь является то, что веб-пакет по существу создает экземпляры каждого модуля в таких общих фрагментах, как этот. Таким образом, каждая библиотека будет иметь свою собственную версию модуля в общих фрагментах.

person Tolu Idowu    schedule 25.10.2019