Плагин Webpack SplitChunks - почему установка приоритета чанка делает его инициализацию асинхронной? - PullRequest
0 голосов
/ 30 января 2019

У меня проблемы с пониманием поведения плагина Webpack splitChunks.Я работаю над переписыванием старых скриптов на существующем сайте в компоненты и использованием Webpack для объединения.Связки просто JS, большинство загружается в конце тела.Но один маленький скрипт должен быть в заголовке страницы, так как он также создает несколько глобальных методов, используемых позже в заголовке и в теле, в основном в виде встроенных скриптов.Так как он используется для отслеживания GA, он не изменится, события должны быть отправлены как можно скорее.

Следующая конфигурация работает для меня, но вопрос почему это работает только так?

Точный вопрос в комментарии в приведенном ниже коде, но я также выкладываю его здесь: Я не понимаю, зачем также включать !isUsedInAppHeaderв состояние для куска common.Без !isUsedInAppHeader в условии чанк common.header не создается.Затем, когда я пытаюсь исправить это путем добавления более высокого приоритета для блока common.header, это приводит к асинхронной инициализации сценариев в app.header.js.

Асинхронное поведение - это то, чего я не делаюпонять вообще, как это никогда не происходит в app.js.

У меня есть другой подвопрос, на самом деле.Можно ли экспортировать общий блок, который также сразу инициализируется?Или вы бы предложили другое решение вообще?Скрипты в заголовке не могут быть перемещены и должны также инициализироваться синхронно, поскольку его основная роль заключается в создании глобальных методов для отслеживания GA, которые должны и должны использоваться немедленно в следующем коде.

Спасибо!

Конфигурация веб-пакета:

...
gulp.task('webpack', function(callback) {
    var settings = {
        ...
        entry: {
            'app.header':   './js/app.header.js',
            'app':          './js/app.js',
            ... // page specific files etc.
        },
        ...
        optimization: {
            splitChunks: {
                cacheGroups: {
                    // Node modules used in app.js
                    vendorsApp: {
                        test(module, chunks) {
                            let isInAppEntryPoint = chunks.map(chunk => chunk.name).includes('app');
                            let isNodeModule = /\/node_modules\//.test(upath.normalize(module.resource));
                            return isInAppEntryPoint && isNodeModule;
                        },
                        name: 'vendors',
                        chunks: 'all',
                        enforce: true,
                    },
                    // Modules shared between app.header and any other file
                    commonHeader: {
                        test(module, chunks) {
                            let isUsedInHeader = chunks.map(chunk => chunk.name).includes('app.header');
                            return isUsedInHeader;
                        },
                        name: 'common.header',
                        chunks: 'initial',
                        minChunks: 2,
                        minSize: 0,
                        // priority: 2  // (*)
                    },
                    // Modules shared between app.js and any other file
                    common: {
                        test(module, chunks) {
                            // QUESTION I don't understand why is it necessary to also include !isUsedInAppHeader into the condition.
                            //          Without the !isUsedInAppHeader in the condition no common.header chunk is created.
                            //          Then, when I try to fix it via adding priority (*) for common.header, it results
                            //          in asynchronous initialisation of the scripts in the app.header.js
                            let isUsedInApp = chunks.map(chunk => chunk.name).includes('app');
                            let isUsedInAppHeader = chunks.map(chunk => chunk.name).includes('app.header');
                            return isUsedInApp && !isUsedInAppHeader;
                        },
                        name: 'common',
                        chunks: 'initial',
                        minChunks: 2,
                    },
                }
            }
        },
    };

    var bundle = webpack(settings, function(error, stats) {
        ...
    });

    return bundle;
});

Таким образом, скрипты загружаются на страницу:

<!DOCTYPE html>
<html lang="en">
    <head>
        ...
        <script src="/js/common.header.js"></script>
        <script src="/js/app.header.js"></script>
        <script>
            ... // Immediate calling of some of the the global methods defined in app.header
        </script>
    </head>
    <body>
        ...
        <script src="/js/vendors.js"></script>
        <script src="/js/common.js"></script>
        <script src="/js/app.js"></script>
        <script src="..."></script>  // page specific files etc.
    </body>
</html>

1 Ответ

0 голосов
/ 27 февраля 2019

Как говорит плагин SplitChunks :

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

Чтобы все работало так, как вы хотите, вы должны использовать настройку по умолчанию chunks: async, чтобы начальные чанки оставались в ваших точках входа.Я полагаю, что другой вариант в вашей настройке будет использовать chunks: all для общего.Если вы хотите пойти по этому пути, обратитесь к этому руководству.

Но я не рекомендую эту стратегию.Поскольку webpack4 и HTML2 поддерживаются большинством cdns, лучше разрешить webpack автоматически разбивать фрагменты и асинхронно загруженные части, которые вы определяете с помощью синтаксиса import. .

имеют 1 точку входа и точки разделения кода , которые вы указываете явно.Если вы не хотите поддерживать импорт модулей es6 в сборке вашего веб-пакета, вы можете использовать синтаксис require.ensure .Я не рекомендую его, если ваша кодовая база не заставляет вас его использовать.

Предварительная загрузка с помощью магических комментариев - это еще одно преимущество синтаксиса import.then().Вы добавляете префикс комментария, например /* webpackHint */, к вызову import, чтобы указать поведение при загрузке.

...