The module specifications supported by webpack includeAMD 、CommonJS、ES2015 import etc. Regardless of the specification, it can be roughly divided into two situations: synchronous loading and asynchronous loading. This article will introduce how webpack implements module management and loading.
The synchronous loading is as follows:
import a from './a'; (a);
Asynchronous loading is as follows:
import('./a').then(a => (a));
The startup function implemented by webpacks directly passes the entry program module into the startup function and caches it in the closure, as follows:
(function(modules){ ...... // Load the entry module and export (implement the starter program) return __webpack_require__(__webpack_require__.s = 0); })({ 0: (function(module, __webpack_exports__, __webpack_require__) { = __webpack_require__(/*! ./src/ */"./src/"); }) })
In implementing module management, webpack is roughly the same regardless of server or client. It mainly records the loaded chunks by installedChunks, and installedModules records the executed modules, as follows:
/** * module cache * key is moduleId (usually file path) * value is module object {i: moduleId, l: false, exports: {}} */ var installedModules = {}; /** * chunks loading status logger * key is generally chunk index * value undefined: not loaded 0: already loaded (client-specific null: ready to load [resolve, reject]: loading) */ var installedChunks = { "app": 0 }
The method of synchronous loading is the same whether it is the server or client. It mainly detects whether the module to be loaded has been cached in installedModules. If there is, it will be returned directly. Otherwise, a new module will be created and the return will be executed. The specific implementation is as follows:
// Synchronous loading after compilation__webpack_require__(/*! ./src/ */"./src/"); // The method of loading the module, that is, the require methodfunction __webpack_require__(moduleId) { // Check whether the current module is already in the cache if(installedModules[moduleId]) { return installedModules[moduleId].exports; // Directly return to cached } // Create a new module and add it to the cache var module = installedModules[moduleId] = { i: moduleId, l: false, // Is it already loaded exports: {} // Exposed object }; // Method to execute the current module modules[moduleId].call(, module, , __webpack_require__); // Mark module loading completion status = true; // Return the exports object exposed by module return ; }
Asynchronous loading on the server is to load the chunk through the node's require method and return a promises object. All chunks expose ids and modules objects, and the specific implementation is as follows:
// Compiled asynchronous loading method__webpack_require__.e(/*! import() */ 0).then(__webpack_require__.bind(null, /*! ./ */ "./src/")) // The chunk 0 code is as follows (i.e. the code) = [0]; = { "./src/": (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); __webpack_exports__["default"] = (function () { ('c'); }) }) } // Asynchronous loading module method__webpack_require__.e = function requireEnsure(chunkId) { var promises = []; if(installedChunks[chunkId] !== 0) { var chunk = require("./" + ({}[chunkId]||chunkId) + ".js"); var moreModules = , chunkIds = ; for(var moduleId in moreModules) { modules[moduleId] = moreModules[moduleId]; } for(var i = 0; i < ; i++) installedChunks[chunkIds[i]] = 0; } return (promises); }
Asynchronous loading of the client is to load resources through JSONP principle, store chunk content ([chunkIds, modules]) into the global webpackJsonp array, and transform the push method of webpackJsonp to listen for chunk loading completion events. The specific implementation is as follows:
// Compiled asynchronous loading method__webpack_require__.e(/*! import() */ 0).then(__webpack_require__.bind(null, /*! ./ */ "./src/")) // The chunk 0 code is as follows (i.e. the code)(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0],{ "./src/": (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); __webpack_exports__["default"] = (function () { ('c'); }); }) }]); // The callback function that was successfully loadedfunction webpackJsonpCallback(data) { var chunkIds = data[0]; var moreModules = data[1]; // Mark the chunk loaded this time as the loading completion status and execute the callback var moduleId, chunkId, i = 0, resolves = []; for(;i < ; i++) { chunkId = chunkIds[i]; if((installedChunks, chunkId) && installedChunks[chunkId]) { (installedChunks[chunkId][0]); // Add chunk successfully callback to the queue to be executed } installedChunks[chunkId] = 0; // Mark the chunk as loading completed } // Add the module loaded this time to the global modules object for(moduleId in moreModules) { if((moreModules, moduleId)) { modules[moduleId] = moreModules[moduleId]; } } // Determine whether the original push method of webpackJsonp array exists. If it exists, the data will be appended to webpackJsonp if(parentJsonpFunction) parentJsonpFunction(data); // Execute all chunk callbacks while() { ()(); } }; // Implementation of the listening method after loadingvar jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || []; var oldJsonpFunction = (jsonpArray); = webpackJsonpCallback; jsonpArray = (); for(var i = 0; i < ; i++) webpackJsonpCallback(jsonpArray[i]); var parentJsonpFunction = oldJsonpFunction; // Asynchronous loading module method__webpack_require__.e = function requireEnsure(chunkId) { var promises = []; var installedChunkData = installedChunks[chunkId]; if(installedChunkData !== 0) { // When 0 means that the installation has been completed if(installedChunkData) { // loading (installedChunkData[2]); } else { // Create a callback Promise and cache the Promise into installedChunks var promise = new Promise(function(resolve, reject) { installedChunkData = installedChunks[chunkId] = [resolve, reject]; }); (installedChunkData[2] = promise); var script = ('script'); var onScriptComplete; = 'utf-8'; = 120; if (__webpack_require__.nc) { ("nonce", __webpack_require__.nc); } = jsonpScriptSrc(chunkId); var error = new Error(); onScriptComplete = function (event) { // Complete callback // Avoid IE memory leaks. = = null; clearTimeout(timeout); // Turn off the timeout timer var chunk = installedChunks[chunkId]; if(chunk !== 0) { // Not loaded if(chunk) { // loading var errorType = event && ( === 'load' ? 'missing' : ); var realSrc = event && && ; = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')'; = 'ChunkLoadError'; = errorType; = realSrc; chunk[1](error); } installedChunks[chunkId] = undefined; } }; var timeout = setTimeout(function(){ // Set the timeout timer onScriptComplete({ type: 'timeout', target: script }); }, 120000); = = onScriptComplete; // Set the loading completion callback (script); } } return (promises); };
For more information, you can view the compiled codeClient、Server side
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.