Webpack pack file core source code interpretation
Please read this page with the source code
This article mainly analyzes the Webpack packaged source code; In the case of a problem with a Webpack package file, we can debug the location according to the basic program structure. For example, after executing the Webpack build and placing the generated files in the dist directory, we analyzed the built.js in the dist directory.
1. Webpack-related configuration for the sample project:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
devtool: 'none',
mode: 'development',
entry: './src/index.js',
output: {
filename: 'built.js',
path: path.resolve('dist')
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
}
2. Main structure
- The packaged file is a function called by itself, passing in an object when the current function is called
- This object, which we’ll call a module definition for convenience, is a key-value pair
- The key name is a concatenation of the file name of the currently loaded module and a directory ().
- This key is a function, similar to Node.js module loading, which wraps the contents of the loaded module in a function
- This function will be called at some point in the future and will receive parameters that will be used to load the module
- For the above code, you pass the module definition: {” module id”:(function(){})} to modules
(function(modules){ //.... })({" module id":(function(){})}))
- Example:
(function (modules) { // webpackBootstrap //.... })({"./ SRC /index.js": (function (module, exports) {console.log('index.js content ') module.exports = 'export content'})});
3. Build the process
See subsequent articles on the Webpack build process and how to generate code structures such as packaging files.
4, Create Compiler Object Compiler, embed core hooks 5, Execute method compiler.run(), 6. Execute method compiler.pile () to complete the compile and output the file
4. Core functions (to be added)
Var instAlledModules = {}; var instAlledModules = {}; // Exports function __webpack_require__(moduleId) {// Exports function __webpack_require__(moduleId) {// Exports function __webpack_require__(moduleId) {// Saves the module definition, __webpack_require__. M = modules; __webpack_require__. C = instAlledModules; // Save all the modules' cache data as a copy. // return true __webpack_require__. O = function (object); // return true __webpack_require__. property) { return Object.prototype.hasOwnProperty.call(object, property); }; // If the name attribute does not exist on the current exports, the condition holds. Getter __webpack_require__. D = function (exports, name, getter) {if (! __webpack_require__.o(exports, name)) { Object.defineProperty(exports, name, { enumerable: true, get: getter }); }}; // define __esModule on exports // R = function (exports) {// Exports (exports) {// Exports (exports) {// Exports (exports); == 'undefined' &&Symbol.toStringTag) {// Add an attribute to exports with the value Module; / / this value by the Object. The prototype. ToString. Call (exports) access to the Object. DefineProperty (exports, Symbol toStringTag, {value: 'Module' }); } // If this is not true, we can also add an __esModule property directly to the exports Object, with the value true Object.defineProperty(exports, '__esModule', {value: true }); }; // If module is an ES Modules module, Return default // GetDefaultPort function for compatibility with non-harmony modules __webpack_require__. N = function (module) { var getter = module && module.__esModule ? function getDefault() { return module['default']; } : function getModuleExports() { return module; }; __webpack_require__.d(getter, 'a', getter); return getter; }; // __webpack_public_path__ __webpack_require__.p = ""; Return __webpack_require__(__webpack_require__. S = "./ SRC /index.js"); // __webpack_require__.
The __webpack_require__. R method adds flags:
__webpack_require__. D adds a getter method to the attribute age (which returns age) :
5. Some knowledge about core functions
1. How to call?
- Executive function
- Call (obj, pra1, pra2…)
2. Object.defineProperty:
- Enumerable parameter, get parameter
- Reference: https://developer.mozilla.org…
3. Symbol.toStringTag
- Symbol.toStringTag is a built-in Symbol that is typically used as an object’s property key
- The corresponding property value for the object should be of type string, which represents the custom type tag for the object
- Usually only built-in Object. The prototype. The toString () method to read the label and put it in his own return values.
- Reference: https://segmentfault.com/a/11…
4. According to the function of bit and, it can realize the judgment of custom conditions
// (1) 1, 2, 4, 8 can be regarded as four fixed switches, and mode can determine whether a switch is turned on or not by setting the corresponding value: // (2) 0001, 0010, 0100, 1000 are the four binary switches and mode "&and operation" can be used to determine whether the corresponding switch type.
6. Function usage scenarios
1. CommonJS module packaging, Webpack default using CommonJS specification for packaging content:
- If the module is imported using CommonJS, Webpack does not require additional processing.
let obj = require('./login.js')
- If the module is exported using CommonJS, Webpack requires no extra processing.
Module. exports = 'EDUCATION'
2. ES Modules
- If the module is imported using ES Modules, Webpack handles it.
import name, { age } from './login.js'
- If the module is exported using ES Modules, Webpack handles it.
Export default 'education' export const age = 100
- Examples of importing and exporting with ES Modules:
(function (modules) { // webpackBootstrap //... return __webpack_require__(__webpack_require__.s = "./src/index.js"); ({}) / / modules as parameters: {KEY: VALUE} ". / SRC/index. Js ": (function (module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); // Tags Es Modules var _login_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./ SRC /login.js"); // Load login.js module console.log('index.js content is loaded ') console.log(_login_js__WEBPACK_IMPORTED_MODULE_0__["default"], '---->', _login_js__WEBPACK_IMPORTED_MODULE_0__["age"]) }), "./src/login.js": (function (module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); __webpack_require__.d(__webpack_exports__, "age", function () { return age; }); __webpack_exports__["default"] = (' pull education '); const age = 100 }) });
7. Execution process of module loading on demand (important)
Load the sample code:
// idnex.js let oBtn = document.getElementById('btn') oBtn.addEventListener('click', function () { import(/*webpackChunkName: "Login" * / ")/login) js'), then ((login) = > {the console. The log (login)})}) console. The log (' index. Js performed)
// login.js module.exports = "Loads exports lazily"
Loading process combing:
- After triggering the asynchronous load of the module, the __webpack_require__. E method is first executed
- The __webpack_require__. E method loads a JS file and returns a promise
-
E Method Function 1: Determine whether a module has been loaded
- Already loaded => using local cache
- Not loaded => Continue loading
-
Function 2 of Method E: JSONP is used to load JS file module
How does JSONP load a JS module?
- Create a script tag in HTML. The SRC of the script tag points to the js file
- The callback method is defined in the JS file and executed when the JS file is loaded
-
Global variables: Variable assignment, define some aliases to facilitate global call after module load
- WebpackJsonp = jsonpArray // no code, which indicates equal
- webpackJsonp.push = jsonpArray.push = webpackJsonpCallback
-
Executives the callback method when loading the JS text: webpackjsonp.push (how do jsonp and promise match here?)
- WebpackJsonP.push is defined in advance, and the actual WebpackJsonpCallback is called in the module
- WebpackJsonpCallback is used to merge asynchronously loaded modules into modules and change the Promise state.
-
Then the __webpack_require__. T method is executed to load the module and return its contents
- T method function: Load the module content, process it according to the module import method (CommonJS or ES Modules), and then export.
- It involves the function design of bitwise and:
- Note: & and operation, binary number a bit of both the same return 1, different return 0
- For example, 0001, 0010, 0100, 1000 are four binary switches 1/2/4/8, 7 means the switch of 1,2,4 is turned on; 8 Close means
- Finally, you take the exported content of the module and use its data to execute subsequent code
The problem is that when using Single-Spa to dynamically load files with the same name from different subsystems, the module name ID may conflict
Webpack5 packaging source code example
Special thanks: pull gou education front-end high salary training camp