У меня проблемы с пониманием поведения плагина 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>