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?