Как webpack реализует динамический импорт

Webpack

предисловие

В одностраничных приложениях веб-пакетыдинамический импортФункция для асинхронной загрузки модулей, что позволяет уменьшить размер некоторых файлов. Мы можем предоставить через webpackimport()а такжеrequire.ensureДва API для использования этой функции.Поскольку оба метода принципиально одинаковы, примеры в этой статье основаны наimport()метод.

начни с примера

основная среда

webpack 4.35.3

код

Вот самый простой пример, есть два файла,index.jsэто входной файл, который используетimport()импортировать динамическиasync.jsдокумент.

index.js


async.js

мы выступаемwebpack --mode=developmentчтобы получить скомпилированный файлmain.jsа также0.js. в,main.jsВключатьindex.jsкод,0.jsВключатьasync.jsкод.

анализировать

главный вход

первый,main.jsФайл служит точкой входа для всего приложения, давайте посмотрим, что внутри.

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

В основной функции он будет выполнять__webpack_require__(__webpack_require__.s = "./src/index.js");для инициализации входного модуля.

Функция этой функции заключается в загрузке и выполнении указанного модуля и возврате модуля.module.exports. Здесь вызывается исполнительный модульmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);для выполнения ранее переданногоmodule, то есть,преобразованныйindex.js.

Давайте посмотрим на код в нем.

Обнаружитьimportбыл преобразован в__webpack_require__.e(/*! import() */ 0), пойдем по следу и продолжим смотреть__webpack_require__.eсделал что-то.

__webpack_require__.e

Код может быть немного ошеломляющим, но это не что иное, как делать что-то подобное.

  1. согласно сinstalledChunksПроверьте, загружен ли онchunk
  2. Если не загружено, инициируйтеJSONPзапрос на загрузкуchunk
  3. Настройте обработку ошибок для запроса, затем вернитеPromise.

Когда обещание вернется, оно продолжит выполнять наш предыдущий асинхронный обратный вызов запроса.

__webpack_require__.e(/*! import() */ 0)
    .then(
        __webpack_require__.bind(null, /*! ./async */ "./src/async.js")
    )...

прямо звонил сюда__webpack_require__загрузить наш异步模块.

Тут два вопроса?

  1. __webpack_require__основано на том, что мы передали ранееmodulesполучитьmodule, однако, в__webpack_require__.eне видел ни одногоmodulesКод для выполнения действия. ЭтоmodulesВ конце концов это когда он обновится?
  2. promiseПучокresolveа такжеrejectвсе депонированоinstalledChunks, не получается получить асинхронные чанкиonloadвыполнить в обратном вызовеresolve,Так,resolveКогда оно было исполнено?
var promise = new Promise(function(resolve, reject) {
    installedChunkData = installedChunks[chunkId] = [resolve, reject];
});

С сомнениями, давайте взглянем на загруженный0.jsсодержание в .

Асинхронный блок

0.js

Логика здесь тоже очень проста, достаточно перейти кwindow["webpackJsonp"]вpush chunkIdи содержитmodules. давайте искатьwindow["webpackJsonp"], найти вmain.jsЕсть такой кусок кода.

обычай здесьwebpackJsonpCallbackфункциязаменятьохватыватьwindow["webpackJsonp"]изpushметод. Итак, прежде чем мы0.jsреализованоpushНа самом деле этореализован пользовательскийwebpackJsonpCallbackфункция.

webpackJsonpCallback

Как видите, webpackJsonpCallback делает две вещи.

  1. воплощать в жизньinstalledChunksсерединаresolve, Позволятьimport()можно продолжать выполнять.
  2. БудуchunkВсе модули, содержащиеся в нем, зарегистрированы наmodulesв переменной.

Теперь мы окончательно разобрались со всем процессом асинхронной загрузки.

more

На самом деле приведенный выше код является лишь самым простым случаем, и конкретное содержание сгенерированной функции будет другим, поскольку код будет другим. Например, мы добавляем код предварительной загрузкиimport(/* webpackPrefetch: true */'./preload');, Сгенерированоmain.jsВ файле будет код для поддержки этой функции.Нетрудно понять, что цель веб-пакета - контролировать размер сгенерированного файла, и студенты, которые интересуются конкретными деталями, могут попробовать его локально.