В этой статье около 1500 слов, на прочтение статьи уходит около 10 минут, а на пробу - 1 час. Если есть ошибки, поправьте меня.
первоначальное намерение
Webpack4 отсутствует уже два месяца, и я обнаружил, что все, включая меня, все еще находятся на стадии изучения использования splitChunk. Я также просмотрел множество демонстраций конфигурации других людей, и я чувствую, что я не очень доволен или не очень доволен.На вопросы, приведенные ниже, никто не ответил, поэтому я могу только управлять ими сам и записывать их между прочим.Если у вас есть лучший, пожалуйста, оставьте адрес в области комментариев.
Общие параметры
- minSize (по умолчанию 30000): наименьший размер для формирования нового блока кода.
- minChunks (по умолчанию 1): минимальное количество ссылок на этот блок кода перед разделением.
- maxInitialRequests (по умолчанию 3): максимальное количество параллельных запросов для записи
- maxAsyncRequests (по умолчанию — 5): максимальное количество параллельных запросов при загрузке по требованию.
- куски (по умолчанию асинхронные): начальные, асинхронные и все
- test: используется для контроля того, какие модули соответствуют этой группе кеша. Если передано как есть, по умолчанию будут выбраны все модули. Типы значений, которые можно передавать: RegExp, String и Function.
- имя (имя упакованных чанков): строка или функция (функция может настроить имя по условиям)
- Приоритет: пакеты группы кэша имеют приоритетную приоритет.
Если вы все еще не знакомы с этими конфигурациями, потяните до конца и посмотрите документацию.
текст
Давайте сначала рассмотрим все конфигурации, а затем пробежимся по общим требованиям в соответствии с демонстрацией.
optimization: {
splitChunks: {
chunks: "async", // 必须三选一: "initial" | "all"(推荐) | "async" (默认就是async)
minSize: 30000, // 最小尺寸,30000
minChunks: 1, // 最小 chunk ,默认1
maxAsyncRequests: 5, // 最大异步请求数, 默认5
maxInitialRequests : 3, // 最大初始化请求书,默认3
automaticNameDelimiter: '~',// 打包分隔符
name: function(){}, // 打包后的名称,此选项可接收 function
cacheGroups:{ // 这里开始设置缓存的 chunks
priority: 0, // 缓存组优先级
vendor: { // key 为entry中定义的 入口名称
chunks: "initial", // 必须三选一: "initial" | "all" | "async"(默认就是async)
test: /react|lodash/, // 正则规则验证,如果符合就提取 chunk
name: "vendor", // 要缓存的 分隔出来的 chunk 名称
minSize: 30000,
minChunks: 1,
enforce: true,
maxAsyncRequests: 5, // 最大异步请求数, 默认1
maxInitialRequests : 3, // 最大初始化请求书,默认1
reuseExistingChunk: true // 可设置是否重用该chunk
}
}
}
},
Давайте посмотрим на первый пример
entry: {
pageA: "./pageA", // 引用utility1.js utility2.js
pageB: "./pageB", // 引用utility2.js utility3.js
pageC: "./pageC" // 引用utility2.js utility3.js
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
chunks: "initial",
minChunks: 2,
maxInitialRequests: 5, // The default limit is too small to showcase the effect
minSize: 0 // This is example is too small to create commons chunks
}
}
}
},
Результат как на рисунке, все в норме. commons~pageB~pageC.js, в соответствии с приведенным выше кодом, ссылка на утилиту2 здесь трижды, сначала она извлекается из commons~pageA~pageB~pageC.js, а затем на утилиту3 ссылаются дважды и помещают в commons~pageB~ pageC.js, в конце концов, есть только один раз ссылка на утилиту1.js, и она прямо помещается в pageA.js.Если утилита1.js здесь также дважды, он все равно создаст новый чанк и поместит его в вместо объединения с общим ресурсом ~pageB~pageC.js, он будет объединен, если на него нет ссылки в записи.
mpageA.js pageB.js pageC.js
Есть место, которое нужно оптимизировать, то есть кода pageA.js pageB.js pageC.js не так много, но пакет очень большой, в нем должны быть какие-то работающие файлы вебпака, прямо добавитьruntimeChunk
runtimeChunk: "single"
// 等价于
runtimeChunk: {
name: "manifest"
}
Теперь просто отлично
Относится к сторонним модулям pageA относится к vue.js pageB относится к react response-dom
vendor: {
test: /node_modules/,
chunks: "initial",
name: "vendor",
priority: 10,
enforce: true
}
Однако в этом случае все библиотеки страницы A, страницы B, страницы C будут упакованы вместе в vendor.js.
Что делать, если я хочу разделить этот vendor.js на pageA-vendor.js pageB-vendor.js, я долго пытался и нашел самый простой способ удалить поставщика вручную и позволить плагину обрабатывать его автоматически.
splitChunks: {
chunks: "all",
cacheGroups: {
commons: {
chunks: "initial",
minChunks: 2,
maxInitialRequests: 5, // The default limit is too small to showcase the effect
minSize: 0 // This is example is too small to create commons chunks
}
}
},
Позже, после того, как я изменил режим веб-пакета на производственный, я обнаружил, что он не работает.Та же конфигурация, в производственном режиме, запакованные вещи были немного невероятными, и vendor-pageB.js был объединен с pageB.js.
Потом, после долгого метания, не мог понять почему, сам придумал способ, лучше вручную и автоматизировать.
commons: {
chunks: "initial",
minChunks: 2,
maxInitialRequests: 5, // The default limit is too small to showcase the effect
minSize: 0 // This is example is too small to create commons chunks
},
'vendor-pageA': {
test: /vue/, // 直接使用 test 来做路径匹配
chunks: "initial",
name: "vendor-pageA",
enforce: true,
},
'vendor-pageB': {
test: /react/, // 直接使用 test 来做路径匹配
chunks: "initial",
name: "vendor-pageB",
enforce: true,
},
Удачно упаковал то, что хотел.
Динамичное введение
Вы должны быть знакомы с динамическим введением, которое вы называете ленивой загрузкой, и динамически внедрять common-async.js непосредственно на страницы pageA и pageB.Здесь я сначала скажу, что splitChunk должен иметь возможность автоматически обрабатывать асинхронность, аналогичную commonChunk. , так далее.
import(/* webpackChunkName: "common-async.js" */"./common-async").then(common => {
console.log(common);
})
Неплохо, удачно упаковано
Попробуйте еще раз в это время.В этом common-async.js вводится общий код f.js, чтобы увидеть, будет ли он повторно упакован.
f.js был успешно извлечен, а другие файлы не были повторно упакованы, что хорошо.
где обратить внимание
- cacheGroups наследуют и переопределяют элементы конфигурации splitChunk, но test, priority и reuseExistingChunk можно использовать только для настройки групп кеша. .
- Cachegroups Каждый элемент должен быть добавлен лучшие параметры кусков, или не может упаковать то, что вы хотите.
- minSize по умолчанию 30Кб (обратите внимание, что это объем до сжатия), если он меньше 30кб, вы должны установить значение, иначе вы не сможете упаковать то, что хотите, и эту штуку нужно добавить в cacheGroups.
- приоритет В некоторых случаях очень полезно установить приоритет пакетов пакетов.
Вышеприведенный пример настроен с общим доступом, имя здесь можно задать самому, или не задать, я его не ставил, можете попробовать, как оно выглядит, и тогда вы поймете, что имя на самом деле в некоторых случаях это лучше не ставить.
commons: {
chunks: "initial",
minChunks: 2,
maxInitialRequests: 5, // The default limit is too small to showcase the effect
minSize: 0 ,
name: "commons"
},
Суммировать
Видно, что splitChunk очень хорош в автоматической обработке с точки зрения ленивой загрузки, но в многостраничных конфигурациях (разделение разных вендоров по разным страницам), поскольку у него есть свой набор стратегий оптимизации, он часто получает результаты, которые не то, что мы хотим желаемый результат. Эта статья - всего лишь мой первоначальный здравый смысл. Я не изучал исходный код глубоко. Я могу добавить анализ исходного кода splitChunk, когда у меня будет время, и тогда это будет яснее.