Packaging tools to solve the following problems:
- File dependency management Combs dependencies among files
- Resource load management deals with file load order (sequencing and timing) and file load quantity (merge, embed, split)
- Efficiency and optimization management improve development efficiency and complete page optimization
Webpack is a packaging tool for modern Javascript applications. It uses the structure of Tool +plugins. Tool provides basic capabilities such as file dependency management and resource load management. On this basis, a series of plugins are used to enrich the functionality of the packaging tool.
In Webpack, all files are modules. However, Webpack only knows JS modules, so it is necessary to use some Loader plug-ins to convert CSS, images and other files into modules that WebPack knows.
In a Webpack package, modules are represented by module functions. Module runtime can be controlled by converting files into module functions. That is, it is not executed immediately after loading, but only when the module function is called.
Webpack works as follows:
- Recursively build a dependency graph from the entry file.
- Convert all files into module functions.
- Module functions are grouped into bundles based on their dependencies and configuration files.
- The bundle is injected into HTML using script tags. The manifest file manages the running and loading of bundle files.
The packaging rules are as follows: each entry file corresponds to one bundle. This bundle includes the import file module and its dependent modules. Modules that need to be loaded on demand or modules that need to be loaded separately are bundled into other bundles.
In addition to these bundles, there is another bundle that is particularly important: the manifest.bundle.js file, webpackBootstrap. This manifest file is loaded first and is responsible for parsing the other bundles packaged by WebPack to load and execute as required.
Package code parsing
Start by analyzing the manifest file.
It contains three main variables, modules, installedModules, and installedChunks.
The Modules object holds all module functions. Function (module, webpack_exports, webpack_require) {function(module, webpack_exports, webpack_require) {function(module, webpack_exports, webpack_require) { }. All module functions are indexed consecutively. If the index of the module function in the first bundle is 0-7, the index of the module function in the second bundle starts at 8 to ensure that the index corresponds to the module function.
InstalledModules objects hold module objects. Module object is the object obtained by running module functions. It is the standard Commonjs object, and its properties mainly include module ID and exports object. Running webpack is the process of executing module functions to get module objects.
InstalledChunks store promise information of asynchronous loading objects in the structure of resolve, Reject, promise. It is mainly used to mark asynchronous loading modules. Use Promises to facilitate global management of asynchronously loaded modules, and throw JS exceptions if loading times out.
There are three main functions, webpackJsonpCallback,Webpack_require__ and __webpack_require.e
webpackJsonpCallback(chunkIds, moreModules, executeModules){… } is the wrapping function of the bundle. This function is run when the bundle file is loaded. The three parameters of the function correspond to three modules. ChunkIds refers to the ID of the module that needs to be loaded separately, corresponding to installedChunks; ExecuteModules are the ids of modules that need to be executed immediately, typically the ids of module functions that correspond to entry files; MoreModules include all module functions packaged by this bundle. The webpackJsonpCallback first stores the module function in the Modules object; Then handle chunkIds and call resolve to change the state of the promise; Finally, we deal with executeModules, converting the corresponding module functions into module objects.
Webpack_require (moduleId) obtains module objects by running module functions in modules and saves them in installedModules objects.
Webpack_require. e(chunkId) tracks the loading status of the on-demand module by establishing a Promise object and setting a timeout threshold. If the loading times out, a JS exception will be thrown. If you do not need to handle load timeout exceptions, you do not need this function and the installedChunks object and can treat the load on demand module as a normal module.
(function(modules) { // webpackBootstrap
// modules stores module functions
// The module cache, which stores module objects
var installedModules = {};
// objects to store loaded and loading chunks
// Promise for the module to load on demand
var installedChunks = { 2:0 };
// The require function
// require converts modules functions into modules objects,
// Run the module function, which assigns the module's export value to the module object for other modules to call.
function __webpack_require__(moduleId) {
// Check if module is in cache
if(installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
// Start by converting a module's code into a module object
// Create a new module (and put it into the cache)
var module = installedModules[moduleId] = {
i: moduleId,
l: false.// Whether the load is complete
exports: {} // Module output, almost representing the module itself
};
// Execute the module function, that is, Execute the module function. Each module is a function when packaged
modules[moduleId].call(module.exports, module.module.exports, __webpack_require__);
// Flag the module as loaded
module.l = true;
// Return the exports of the module
return module.exports;
}
// install a JSONP callback for chunk loading
var parentJsonpFunction = window["webpackJsonp"];
window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
var moduleId, chunkId, i = 0, resolves = [], result;
// Iterate over chunkIds and save the resolve function if the corresponding module is an on-demand module.
for(; i < chunkIds.length; i++) { chunkId = chunkIds[i];if(installedChunks[chunkId]) {
// Resolve is an on-demand module
resolves.push(installedChunks[chunkId][0]);
}
installedChunks[chunkId] = 0; // The chunk has already been processed
}
// traverse moreModules to store module functions in modules
for(moduleId in moreModules) {
if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { modules[moduleId] = moreModules[moduleId]; }}// Execute the resolve function, usually __webpack_require__
while(resolves.length) {
resolves.shift()();
}
// Traverse moreModules to convert module functions to module objects
if(executeModules) {
for(i=0; i < executeModules.length; i++) { result = __webpack_require__(__webpack_require__.s = executeModules[i]); }}return result;
};
__webpack_require__.e = function requireEnsure(chunkId) {
var installedChunkData = installedChunks[chunkId];
// Once the module has been processed (the module function is loaded and converted to a module object), return promise and call resolve
if(installedChunkData === 0) {
return new Promise(function(resolve) { resolve(); });
}
// The module is being loaded, returning the original promise
// After loading, the module function is run, which calls resolve to change the state of the promise
if(installedChunkData) {
return installedChunkData[2];
}
// Create a new promise and assign all resolve, reject, and promise to installedChunks for global access
var promise = new Promise(function(resolve, reject) {
installedChunkData = installedChunks[chunkId] = [resolve, reject];
});
installedChunkData[2] = promise;
var head = document.getElementsByTagName('head') [0];
var script = document.createElement('script');
script.src = __webpack_require__.p + "" + chunkId + ".bundle.js";
var timeout = setTimeout(onScriptComplete, 120000);
script.onerror = script.onload = onScriptComplete;
function onScriptComplete() {
script.onerror = script.onload = null;
clearTimeout(timeout);
var chunk = installedChunks[chunkId];
if(chunk ! = =0) { // Not processed
if(chunk) {// Load the module on demand, i.e. request time out
chunk[1] (new Error('Loading chunk ' + chunkId + ' failed.'));
}
installedChunks[chunkId] = undefined; }}}}) ([]);Copy the code
Then analyze the normal bundle files.
All the code is wrapped in the webpackJsonp function.
The second argument to the function is an array containing the module functions corresponding to all the packaged files. Function (module, webpack_exports, webpack_require) {function(module, webpack_exports, webpack_require) { }. The code in the module function is the corresponding replacement of the code in the file before packaging. For example, replace require with __webpack_require__, replace the previous path with the new one, and replace import with __webpack_require__.e().then(). Module functions export the module’s exports through statements like __webpack_exports__[“a”] = printMe. Through module functions, amd, CMD, CommJS modules are unified into webpack modules.
webpackJsonp([1], [/* 0 */
(function(module, exports, __webpack_require__) {
module.exports = __webpack_require__.p + "695368065150e6c5683c6642951c74ce.jpg";
}),
/ * 1 * /
(function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
// Load the dependency module
var __WEBPACK_IMPORTED_MODULE_0__style_css__ = __webpack_require__(2); . var __WEBPACK_IMPORTED_MODULE_1__katong_jpg___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1__katong_jpg__); . var __WEBPACK_IMPORTED_MODULE_2__say_js__ = __webpack_require__(7);
// welcome. Js
var elDiv1 = document.createElement('div'); .// Replace the original URL with the image loaded aboveelImg.src = __WEBPACK_IMPORTED_MODULE_1__katong_jpg___default.a; .// Replace import with promise-implemented __webpack_require__.e() for asynchronous on-demand loading
btn.onclick = function() {
__webpack_require__.e(0).then(__webpack_require__.bind(null.8)).then(m= > {
m.default();
});
};
// Replace the original say() function with the one loaded above
Object(__WEBPACK_IMPORTED_MODULE_2__say_js__["a") (); }),/ * 2 * /
(function(module, exports, __webpack_require__) {... }),.../ * * / 6
(function(module, exports) {... }),/ * * / 7
(function(module, __webpack_exports__, __webpack_require__) {
// Module output
__webpack_exports__["a"] = printMe;
function printMe() {... }})], [1]);
Copy the code
Here are some concepts for webPack configuration
Entry
The entry file is the starting point for WebPack to build the dependency diagram.
Output
The Output configuration tells WebPack what to do with the packaged code.
Hot Module Replacement
The hot module replacement function can be implemented without refreshing all the files to create a single module.
Tree Shaking
Remove useless code, such as a function in a JS file that is not used, the function code will be removed when packaging.
Code Splitting
There are three ways to split code
- Entry Points manually divide code into multiple entries
- Prevent Duplication extracts common code blocks using the CommonsChunkPlugin
- Dynamic Imports use the import function to dynamically import modules
Lazy Loading
Lazy loading or loading on demand is part of Code Splitting
Loaders
Webpack treats all files as modules, but it only understands Javascript. Loaders converts these files, unknown to WebPack, into modules for WebPack to process.
plugins
Plug-ins typically handle compilation of packaged modules or work related to code blocks.
The Manifest
The Webpack manifest file is used to guide all module interactions. The manifest file contains the logic for loading and processing modules.
As the Webpack compiler processes and maps application code, it records module details in the manifest file. When the module is packaged and shipped to the browser, the Runtime processes and loads the module according to the manifest file. Use manifest to know where to get the module code.
The instance
The corresponding examples of the above analysis are in this project. In the dist-comment folder are the files generated by build, annotated. For the sake of illustration, the above analysis has adjusted the order of the code and removed some of the code, so it is not exactly the same as the files in the dist- Comment folder.
Based on the above analysis, you can better understand how WebPack works by comparing the source code with the built code.
Running steps
- npm install
- npm run build
The original link
This is forwarding other people’s articles, feel particularly good, to share, if there is infringement, please contact deletion