How webpack is modular loading

webpack support module specifications have  AMD  , CommonJS , ES2015 Import  and other norms. Regardless of the load specification can be divided into synchronous and asynchronous loading two cases. This article describes how to achieve webpack management module and loaded.

Synchronous load as follows:

import a from './a';
console.log(a);

Asynchronous loading as follows:

import('./a').then(a => console.log(a));

webpacks achieved startup function, passed directly to the entry program start function module, and the cache in a closed package, as follows:

(function(modules){
......
// Load the inlet module and export (to achieve start the program)
return __webpack_require__(__webpack_require__.s = 0);
})({
0: (function(module, __webpack_exports__, __webpack_require__) {
module.exports = __webpack_require__(/*! ./src/app.js */"./src/app.js");
})
})

webpack in the realization management module regardless of server or client is roughly the same module consists installedChunks records already loaded chunk, installedModules recording has been performed, as follows:

/**
* Module buffer
* Key is moduleId (usually file paths)
* Value of the object module {i: moduleId, l: false, exports: {}}
*/
var installedModules = {};
/**
* Chunks loading state recorder
* Key is generally chunk index
* Value undefined: not loaded 0: already loaded (client-specific null: ready to load [resolve, reject]: Loading)
*/
was installedChunks = {
"app": 0
}

Regardless of the method is the server or the client synchronization load are the same, mainly to whether there is a cache module to load detection installedModules, there is a direct return, if not, create a new module, and do a return module.exports, the specific implementation as follows:

// sync load after compiling
__webpack_require__(/*! ./src/app.js */"./src/app.js");

Method // load modules, i.e., require methods
function __webpack_require__(moduleId) {
// Check if the current module already exists in the cache
if(installedModules[moduleId]) {
return installedModules [moduleId] .exports; // return directly cached module.exports
}
// Create a new module, and add to the cache
var module = installedModules[moduleId] = {
i: moduleId,
l: false, // is already loaded
exports: {} // objects exposed
};
// execute the method of the current module
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
// marking module loaded state
module.l = true;
// return the object module exports exposed
return module.exports;
}

The server is asynchronous loading by loading chunk require method promises a node and returns the object. All chunk ids are exposed objects and modules, specifically to achieve the following:

// asynchronous loading method compiled
__webpack_require__.e(/*! import() */ 0).then(__webpack_require__.bind(null, /*! ./c.js */ "./src/c.js"))

// chunk 0 following codes (i.e., codes of 0.js)
exports.ids = [0];
exports.modules = {
"./src/c.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
__webpack_exports__["default"] = (function () {
console.log('c');
})
})
}

// asynchronous loading modular approach
__webpack_require__.e = function requireEnsure(chunkId) {
var promises = [];
if(installedChunks[chunkId] !== 0) {
var chunk = require("./" + ({}[chunkId]||chunkId) + ".js");
var moreModules = chunk.modules, chunkIds = chunk.ids;
for(var moduleId in moreModules) {
modules[moduleId] = moreModules[moduleId];
}
for(var i = 0; i < chunkIds.length; i++)
installedChunks[chunkIds[i]] = 0;
}
return Promise.all(promises);
}

Asynchronous loading client is through the principle of JSONP to load resources, the chunk content ([chunkIds, modules]) to keep global webpackJsonp array and the push method to achieve the transformation webpackJsonp listening chunk loaded event. Specific achieve the following:

// asynchronous loading method compiled
__webpack_require__.e(/*! import() */ 0).then(__webpack_require__.bind(null, /*! ./c.js */ "./src/c.js"))

// chunk 0 following codes (i.e., codes of 0.js)
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0],{
"./src/c.js": (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
__webpack_exports__["default"] = (function () {
console.log('c');
});
})
}]);

// Load the success callback function
function webpackJsonpCallback(data) {
var chunkIds = data [0];
var moreModules = data [1];

// This will load the back of the chunk is marked as loaded state, and executes the callback
var moduleId, chunkId, i = 0, resolves = [];
for(;i < chunkIds.length; i++) {
chunkId = chunkIds [i];
if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
resolves.push (installedChunks [chunkId] [0]); // add to the chunk success callback queue to be executed
}
installedChunks [chunkId] = 0; // mark as the loaded chunk
}
// add this module is loaded back to the global target of modules
for(moduleId in moreModules) {
if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
modules[moduleId] = moreModules[moduleId];
}
}
Analyzing the original array webpackJsonp // push method exists, the data is appended to the presence of the webpackJsonp
if(parentJsonpFunction) parentJsonpFunction(data);
// perform all chunk callbacks
while(resolves.length) {
resolves.shift()();
}
};

// Load complete the implementation listener methods
var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
jsonpArray.push = webpackJsonpCallback;
jsonpArray = jsonpArray.slice();
for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
was parentJsonpFunction = oldJsonpFunction;

// asynchronous loading modular approach
__webpack_require__.e = function requireEnsure(chunkId) {
var promises = [];
var = installedChunkData installedChunks [chunkId];
if (installedChunkData! == 0) {// 0 indicates that the FTP completed
if (installedChunkData) {// Loading
promises.push(installedChunkData[2]);
} else {
// Create a callback Promise, and the Promise cache to installedChunks
var promise = new Promise(function(resolve, reject) {
installedChunkData = installedChunks[chunkId] = [resolve, reject];
});
promises.push(installedChunkData[2] = promise);

var script = document.createElement('script');
var onScriptComplete;
script.charset = 'utf-8';
script.timeout = 120;
if (__webpack_require__.nc) {
script.setAttribute("nonce", __webpack_require__.nc);
}
script.src = jsonpScriptSrc(chunkId);

var error = new Error();
onScriptComplete = function (event) {// loading completion callback
// IE to avoid memory leaks.
script.onerror = script.onload = null;
clearTimeout (timeout); // close the timeout timer
var chunk = installedChunks [chunkId];
if (chunk! == 0) {// not loaded
if (chunk) {// Loading
var errorType = event && (event.type === 'load' ? 'missing' : event.type);
var realSrc = event && event.target && event.target.src;
error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
error.name = 'ChunkLoadError';
error.type = errorType;
error.request = realSrc;
chunk[1](error);
}
installedChunks[chunkId] = undefined;
}
};
var timeout = setTimeout (function () {// set the timeout timer
onScriptComplete({ type: 'timeout', target: script });
}, 120000);
script.onerror = script.onload = onScriptComplete; // set the loading completion callback
document.head.appendChild(script);
}
}
return Promise.all(promises);
};


Article simultaneous release:  https://www.geek-share.com/detail/2784034803.html

Reference article:

Detailed webpack + react + react-router how to implement lazy loading

Webpack2 + Vue2 + Vue-Router2 how to implement lazy loading?

 


Guess you like

Origin blog.51cto.com/dolunbu/2448339