preface
Webpack is a code compilation and packaging tool, with entry, exit, loader and plug-in, etc. Most front-end developers can skillfully use WebPack to manage our code, but we may not have tried to understand the principle of WebPack compilation. Curious (‘ ヘ´)=3, let’s read the compiled source code and try to understand the basic principle of webpack compilation ヾ(◍°∇) Blue ヾ.
Take the following code for example:
index.html
<! --index.html-->
<html>
<head>
<title>Hello World</title>
<script src='./main.js' />Copy the code
./app/main.js
let message=require('./module1.js');
let app = document.getElementById("app");
app.innerHTML += `<span class="title">${message}</span>`;
Copy the code
./app/module1.js
let message = "Hello World"
module.exports = message;
Copy the code
The Webpack configuration is as follows:
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode:'development'./* Compile configuration */
devtool: 'eval-source-map'./* Import file */
entry: __dirname + "/app/main.js".// The only entry file that has been mentioned several times
output: {
path: __dirname + "/dist".// The place where the packed files are stored
filename: "[name].js"// Output the file name after packaging
},
/* Develop the service configuration */
devServer: {
contentBase: "./dist".// The directory where the page is loaded by the local server
historyApiFallback: true.inline: true
},
plugins: [new HtmlWebpackPlugin({ // Package the output HTML
title: 'Hello World app'.minify: { // Compress HTML files
removeComments: true.// Remove comments from HTML
collapseWhitespace: true.// Remove whitespace and newline characters
minifyCSS: true// Compress inline CSS
},
filename: 'index.html'.template: 'index.html'}),].Loader * / / * configuration
module: {
rules: [{//babel-loader converts the specified file to a browser-recognized JS
test: /(\.jsx|\.js)$/,
use: [
{
loader: "babel-loader"}, {loader:"force-strict-loader".options: {sourceMap:true}}].exclude: /node_modules/ // Unprocessed position}]}};Copy the code
The code above will package./app/main.js and app/module1.js as./dist/main.js and import it in the index.html file.
Compiled code
Next, read the compiled./dist/main.js code to get a feel for how package compilation works. To make it easier to read and understand, we have simplified the code as follows.
(
function (modules) {
// Cache of loaded modules
let installedModule = {};
//CommonJS module load implementation of the core method
function __webpack_require__(moduleId) {
if (installedModule[moduleId]) {
// If the module is loaded, return the module in the cache directly
return installedModule[moduleId];
}
let module = installedModule[moduleId] = {
id: moduleId,
loaded: false.// Whether the load is complete
exports: {} // The external interface of this file module
}
// calls the module loading function that executes the module code and assigns a value to module.exports
modules[moduleId].call(module.exports, module.module.exports, __webpack_require__);
module.loaded = true; // Load complete
// Returns the exported value of this module
return module.exports;
}
// Load the entry file
return__webpack_require__(entry); ({})'./app/main.js': function (module, __webpack_exports__, __webpack_require__) {
// CommonJs import statements for module1 will be compiled to call the __webpack_require__ loading function,
// Returns the exported value for module1, that is, the expots property of the Module object for moduleId='./app/module1.js'
var _module1__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(
/ *! ./module1 */
"./app/module1.js");
// Read the contents of the file
let app = document.getElementById("app");
app.innerHTML += `<span class="title">${_module1__WEBPACK_IMPORTED_MODULE_0__}</span>`;
},
'./app/module1.js': function (module, __webpack_exports__, __webpack_require__) {
let message = "Hello World"
// Modify the exports value of its module object
module.exports = message; }});Copy the code
First webPack compiles each file into a self-executing function, forming a separate scope. This function takes a Modules array object, which is a key-value pair corresponding to the JS file. A few key points to note:
entry
: Import fileinstalledModule
: The module cache object__webpack_require__
: CommonJs module system simulation implementation
Simplify the code
To make the code and execution flow more intuitive, further simplify the code.
// Import file
let entry = './app/main.js';
let installedModule={};// Cache of loaded modules
//CommonJS module load implementation
function __webpack_require__(moduleId){
if(installedModule[moduleId]){
// If the module is loaded, return the module in the cache directly
return installedModule[moduleId];
}
// Construct a new module object
let module=installedModule[moduleId]={
id:moduleId,
loaded:false.// Whether the load is complete
exports: {}// The external interface of this file module
}
// calls the module loading function that executes the module code and assigns a value to module.exports
modules[moduleId].call(module.exports,module.module.exports,__webpack_require__);
module.loaded=true;// Load complete
// Returns the exported value of this module
return module.exports;
}
// Webpack generates an object corresponding to each js= file, which is a key-value pair {filename: execute function},
// Executes its own function within a function and recursively calls __webpack_require__ to load other modules on which it depends
let modules={
'./app/main.js':function ( module, __webpack_exports__ , __webpack_require__){
// CommonJs import statements for module1 will be compiled to call the __webpack_require__ loading function,
// Returns the exported value for module1, that is, the expots property of the Module object for moduleId='./app/module1.js'
var _module1__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(
/ *! ./module1 */ "./app/module1.js");
let app = document.getElementById("app");
app.innerHTML += `<span class="title">${_module1__WEBPACK_IMPORTED_MODULE_0__}</span>`;
},
'./app/module1.js':function ( module, __webpack_exports__ , __webpack_require__){
let message="Hello World"
// Modify the exports value of its module object
module.exports=message; }};// Load the entry file
__webpack_require__(entry);
Copy the code
The above code is easy to understand by referring to the comments provided, and is briefly explained here.
- The js file is compiled to produce an example
modules
Object, which is a collection of compiled source code for all JS files, expressed in the form of key-value pairs, the key is the file path, the value is a function to execute the source code; - Each JS file corresponds to a Module object, one for each object
exports
Property, this oneexports
Property is the external interface used to export file contents;
Exports :{} // moduleId, loaded:false,// exports:{} // moduleId, loaded:false,// exports:{}Copy the code
installedModule
Is amodule
Object, all of which are stored as key-value pairsmodule
The cache.- When we go through
__webpack_require__(entry)
When loading the entry file, we first checkinstalledModule
If yes, return the cached module directly. If no, create an object and save it in the cache. Then executemodule
withmodules
In themoduleId
The corresponding function is executedmodule
Source code, and through modificationmodule.exports
Property exports the values in this module. - If the js file has dependencies on other files, that is, require references to other files, translate to
var _module1__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./app/module1.js");
Statement, continue to call__webpack_require__
Function into the module,__webpack_require__
The function returns the currently imported moduleexports
Properties.
What WebPack does for us is compile the source code we wrote into the form described above. Once we understand the compiled code, we can roughly understand that WebPack needs to do the following things at compile time:
- Read the contents of the JS file
- encounter
require
Line is converted into__webpack_require__
Form of function - Encapsulates the contents of the file as an object, the key is the file path, and the value is a function that executes the compiled JS source code
The above 👆 process is only a general compilation process of JS files. In a real project, there will be multiple Loaders for compiling different types of files, such as vue-loader for compiling. Vue files, CSS-loader for compiling CSS-related codes and files, and TS-loader for compiling. Webpack compiles different types of files based on the loader configured in Modules.
The last
See the following article at 👇 to add your own understanding and code. At the same time, I have also organized a brain map related to webpack principle in the following blog post, which is convenient for memorizing and understanding the process for your reference.
Reference article:Interviewer: Not even webpack? The above is their simple understanding of webpack principle, if there is a mistake also hope to correct, if you have a help welcome to praise 👍 support!