В этой статье объясняется процесс разделения пакета кода в сочетании с splitChunks webpack4 для многостраничного проекта, над которым я недавно работал.
рамки проекта
В проекте есть два входных файла, домашний и тематический, которые в основном включают:
- react, mobx, antd используются как базовый фреймворк проекта,
- echarts (живопись) и d3 (живопись) — относительно большие библиотеки компонентов, используемые некоторыми страницами проекта.
- src код общего компонента проекта и т. д.
- Другой закрытый код.
Оба входных файла загружаются асинхронно с помощью react-loadable
import Loadable from 'react-loadable';
...
const LoadableLogin = Loadable({
loader: () => import('../../common/components/login'),
loading: Loading,
});
...
Некоторые конфигурации веб-пакета следующие:
module.exports = {
...
mode: 'production',
entry: { // 多入口
home: './src/home',
topic: './src/topic',
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath,
},
plugins: [
new HtmlWebpackPlugin({ // home页面
filename: 'home.html',
template: './template.html',
}),
new HtmlWebpackPlugin({ // topic页面
filename: 'topic.html',
template: './template.html',
inject: true,
}),
],
...
}
splitChunks
chunks:
- все: независимо от того, загружается ли файл динамически или нет, файлы равномерно разделены. Все пакеты импортируются при первой загрузке страницы
- async: разделите асинхронно загружаемые файлы, обычно не вводимые в первый раз, до компонентов, которые необходимо импортировать асинхронно.
- Initial: разделяет асинхронные и неасинхронные файлы.Если файл импортируется асинхронно и неасинхронно, он будет упакован дважды (обратите внимание на отличие от всех), чтобы отделить пакет, который страница должна загрузить в первый раз.
minSize: минимальный размер пакета файла в байтах, по умолчанию 30000.
Например, есть три входных файла под неким проектом, a.js, b.js и c.js все по 100 байт, когда мы установим minSize в 301, то webpack упакует их в один пакет и не будет их дизассемблировать. несколько пакетов.
AutomaticNameDelimiter: Соединитель
Предположим, мы создаем общий файл с именем vendor, a.js и b.js зависят от него, а коннектор, который мы установили, равен «~», тогда окончательный сгенерированный файл будет vendor~a~b.js.
maxInitialRequests Максимальное количество параллельных запросов в точке входа, по умолчанию 3
Если мы установим его равным 1, то каждый файл записи будет упакован только в один файл.
maxAsyncRequests максимальное количество асинхронных запросов, по умолчанию 5
Если мы установим его равным 1, то каждый файл записи будет упакован только в один файл.
приоритетное отношение
maxInitialRequest / maxAsyncRequests
cacheGroups настраивает правила разделения пакетов
test может настраивать обычные функции и функции записи в качестве правил упаковки. Другие свойства могут наследовать splitChunks, о чем здесь нужно сказать.приоритет, установите приоритет упаковки пакета, очень важно!(в сочетании с практикой позже)
minChunks
Минимальное количество знакомств
упражняться
Начнем с самой простой конфигурации, котораяобщедоступный кодупаковать его
splitChunks: {
chunks: 'all', // initial、async和all
minSize: 30000, // 形成一个新代码块最小的体积
maxAsyncRequests: 5, // 按需加载时候最大的并行请求数
maxInitialRequests: 3, // 最大初始化请求数
automaticNameDelimiter: '~', // 打包分割符
name: true,
cacheGroups: {
vendors: { // 打包两个页面的公共代码
minChunks: 2, // 引入两次及以上被打包
name: 'vendors', // 分离包的名字
chunks: 'all'
},
}
},
Общий код двух входных файлов упакован в папку поставщика, включая некоторые сторонние пакеты, такие как echarts d3 amcharts и общий код в src.
Это точно не тот результат, который нам нужен! Существуют следующие проблемы:
-
На самом деле, когда мы заходим на сайт, первым шагом является вход на целевую страницу.Все, что нам нужно, это базовый код фреймворка проекта, такой как react, react-dom.antd и т. д. Мы можем использовать все (или начальные ), чтобы упаковать их отдельно как пакеты, которые должны быть загружены на домашнюю страницу
-
Публичный пакет, который мы упаковали, когда страница загружается в первый раз, просто хочу поместитьсинхронная загрузказагружаются, поэтому требуется синхронный общий пакет
-
Например, echarts, d3 и некоторые ниже srcАсинхронная загрузкапакеты, используйте async для их упаковки в один асинхронно загружаемый пакет
Мы модифицируем cacheGroups на:
cacheGroups: {
vendors: { // 项目基本框架等
chunks: 'all',
test: /(react|react-dom|react-dom-router|babel-polyfill|mobx)/,
priority: 100,
name: 'vendors',
},
'async-commons': { // 异步加载公共包、组件等
chunks: 'async',
minChunks: 2,
name: 'async-commons',
priority: 90,
},
commons: { // 其他同步加载公共包
chunks: 'all',
minChunks: 2,
name: 'commons',
priority: 80,
},
}
Пакеты, которые Webpack помог нам набрать на этот раз, в основном включают:
-
async-common: это трехсторонний пакет, в котором оба входных файла загружаются асинхронно, а код отложенной загрузки, созданный react-loader, включая echarts, d3 и т. д.
-
поставщики: включая реакцию, реакцию-дом, антд и т. д.
-
Commons: синхронный код ссылается более чем в два раза
Вот две вещи, на которые следует обратить внимание:
-
Обратите внимание на настройку нашего приоритета здесь, vendors>async-commons>commons, мы сначала упаковываем react, react-dom и т. д., а затем упаковываем публичную часть,Если приоритет вендоров установлен меньше, чем приоритет двух общих, то react, react-dom будут упакованы в общий пакет, а пакет вендоров не будет генерироваться повторно.
-
Если мы удалим здесь конфигурацию commons, будет сгенерирован пакет theme~home, и мы настроили async-commonПосле извлечения асинхронно загруженного общедоступного пакета синхронно загруженный общедоступный пакет будет упакован по умолчанию.Создайте пакет имени «topic~home», сгенерированный соединителем AutomaticNameDelimiter «~», содержимое которого фактически совпадает с содержимым пакета commons.точно так же,
Ok! Согласно нашим требованиям, при загрузке первой страницы будут представлены только пакеты vendors и commons, а пакет async-common не будет представлен, что все равно здорово! Для тех из нас, кто стремится к большему совершенствованию, если мы тщательно обдумаем это, можем ли мы сделать некоторые оптимизации получше?
Упаковка наших упаковочных файлов на данный момент выглядит следующим образом:
После gzip самый большой пакет async-common весит 391 КБ. Компания заявила, что из-за некоторых обстоятельств в последнее время, когда макет после производства работает медленно, иногда скорость загрузки может составлять всего 20 кбит/с ==. . . . Так что продолжайте разделять!Проанализируйте это:
-
async-common включает компоненты src и сторонние компоненты, написанные вами
-
Более крупными в async-common являются echarts, zrender (введенный echarts) и d3.С точки зрения проектов, толькочасть страницыНам нужны echarts (такие же, как d3), поэтому мы можем рассмотреть возможность извлечения двух более крупных пакетов, d3 и echarts, и позволить им загружаться асинхронно, когда это необходимо странице, что значительно снижает общий асинхронный объем.
Исправлять
cacheGroups: {
vendors: { // 基本框架
chunks: 'all',
test: /(react|react-dom|react-dom-router|babel-polyfill|mobx)/,
priority: 100,
name: 'vendors',
},
d3Venodr: { // 将体积较大的d3单独提取包,指定页面需要的时候再异步加载
test: /d3/,
priority: 100, // 设置高于async-commons,避免打包到async-common中
name: 'd3Venodr',
chunks: 'async'
},
echartsVenodr: { // 异步加载echarts包
test: /(echarts|zrender)/,
priority: 100, // 高于async-commons优先级
name: 'echartsVenodr',
chunks: 'async'
},
'async-commons': { // 其余异步加载包
chunks: 'async',
minChunks: 2,
name: 'async-commons',
priority: 90,
},
commons: { // 其余同步加载包
chunks: 'all',
minChunks: 2,
name: 'commons',
priority: 80,
},
}
Разумеется, после каждой модификации нужно настраивать пакеты, требуемые по чанку в htmlWebpackPlugin.
plugins: [
new HtmlWebpackPlugin({ // home页面
filename: 'home.html',
template: './template.html',
chunks: ['vendors', 'commons', 'home'],
}),
new HtmlWebpackPlugin({ // topic页面
filename: 'topic.html',
template: './template.html',
chunks: ['vendors', 'commons', 'topic'],
}),
],
На более позднем этапе также были сделаны другие разбиения и оптимизации.Вероятно, самый большой пакет хранится около 100 КБ.Конечно, не рекомендуется разбивать его на особенно маленький размер, потому что браузер http1 может поддерживать 6 загрузок файлов на время, слишком много может быть контрпродуктивным. Вы можете использовать различные методы разделения в соответствии с вашим собственным проектом.В целом, это должно сделать проект более совершенным в Интернете и предоставить пользователям лучший опыт~