Шаг за шагом, чтобы понять плагин splitChunk для webpack4

внешний интерфейс JavaScript React.js Webpack
Шаг за шагом, чтобы понять плагин splitChunk для webpack4

В этой статье около 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, когда у меня будет время, и тогда это будет яснее.

исходный код

разделение кода

ленивая загрузка кода

Справочная статья

splitChunk китайская версия

splitChunk английская версия

документация веб-пакета

Официальная демоверсия