предисловие
В одностраничных приложениях веб-пакетыдинамический импортФункция для асинхронной загрузки модулей, что позволяет уменьшить размер некоторых файлов. Мы можем предоставить через 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
Код может быть немного ошеломляющим, но это не что иное, как делать что-то подобное.
- согласно с
installedChunksПроверьте, загружен ли онchunk - Если не загружено, инициируйте
JSONPзапрос на загрузкуchunk - Настройте обработку ошибок для запроса, затем вернитеPromise.
Когда обещание вернется, оно продолжит выполнять наш предыдущий асинхронный обратный вызов запроса.
__webpack_require__.e(/*! import() */ 0)
.then(
__webpack_require__.bind(null, /*! ./async */ "./src/async.js")
)...
прямо звонил сюда__webpack_require__загрузить наш异步模块.
Тут два вопроса?
__webpack_require__основано на том, что мы передали ранееmodulesполучитьmodule, однако, в__webpack_require__.eне видел ни одногоmodulesКод для выполнения действия. ЭтоmodulesВ конце концов это когда он обновится?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 делает две вещи.
- воплощать в жизнь
installedChunksсерединаresolve, Позволятьimport()можно продолжать выполнять. - Буду
chunkВсе модули, содержащиеся в нем, зарегистрированы наmodulesв переменной.
Теперь мы окончательно разобрались со всем процессом асинхронной загрузки.
more
На самом деле приведенный выше код является лишь самым простым случаем, и конкретное содержание сгенерированной функции будет другим, поскольку код будет другим. Например, мы добавляем код предварительной загрузкиimport(/* webpackPrefetch: true */'./preload');, Сгенерированоmain.jsВ файле будет код для поддержки этой функции.Нетрудно понять, что цель веб-пакета - контролировать размер сгенерированного файла, и студенты, которые интересуются конкретными деталями, могут попробовать его локально.