The introduction
This article is based on webpack5 source code interpretation, this article is only for the convenience of the author to learn and memory, if there is anything wrong or guess the wrong place, please point out, do not spray, we are all our own thank you ~
start
The idea is, before we learn, the most basic function of WebPack itself is to provide builds, so let’s create a basic file structure so that we can do a basic build.
The first step
First create a folder and run it (the name of the folder is whatever makes you happy)
NPM install webpack webpack-cli --save-dev // Install NPM install lodash --save-devCopy the code
Then create two files named index.js and webpack.config.js
// index.js
import _ from 'lodash'
export default {
cloneDeepWithLog () {
console.log('Deep Clone Obj:'. arguments)return_.cloneDeep(... arguments) } }Copy the code
// webpack.config.js
const path = require('path');
module.exports = {
entry: './index.js'.output: {
filename: 'main.js'.path: path.resolve(__dirname, 'dist'),}};Copy the code
Finally, simply configure the relevant command “build”: “webpack” in package.json and run NPM run build to see the built content in. /dist/main.js. So now that we have a basic project, we’re going to look at what happens when we run commands
The second step
First of all, we need to analyze the process, so we must understand the sequence in the process, and the ways and means of calling each other. So at least we want to have the biggest frame and then we’re going to start digging deeper and deeper into it, and based on what we just did all we know so far is this picture.
NPM run *** will actually go to package.json and look for our corresponding instruction. For example, our corresponding instruction is “build”: “Webpack”, and then when we get webpack it’s going to call NPX webpack and go to./node_modules. Bin
Then we can open our IDE and see that the relevant code is as follows (I have sketched it briefly)
#! /usr/bin/env node
/ * * *@param {string} packageName name of the package
* @returns {boolean} is the package installed? * /
const isInstalled = packageName= > {
try {
require.resolve(packageName);
return true;
} catch (err) {
return false; }};/ * * *@param {CliOption} cli options
* @returns {void}* /
const runCli = cli= > {
const path = require("path");
const pkgPath = require.resolve(`${cli.package}/package.json`);
// eslint-disable-next-line node/no-missing-require
const pkg = require(pkgPath);
// eslint-disable-next-line node/no-missing-require
require(path.resolve(path.dirname(pkgPath), pkg.bin[cli.binName]));
};
/ * * *@typedef {Object} CliOption
* @property {string} name display name
* @property {string} package npm package name
* @property {string} binName name of the executable file
* @property {boolean} installed currently installed?
* @property {string} url homepage
*/
/ * *@type {CliOption} * /
const cli = {
name: "webpack-cli".package: "webpack-cli".binName: "webpack-cli".installed: isInstalled("webpack-cli"),
url: "https://github.com/webpack/webpack-cli"
};
if(! cli.installed) {// Omit a bunch of code, the main point being that if you don't have Webpack-cli installed then you have runCLi installed
} else {
runCli(cli);
}
Copy the code
At the heart of all this code is a function called runCli that does only one thing, Node_modules /webpack-cli/bin/cli.js = node_modules/webpack-cli/bin/cli.js = node_modules/webpack-cli/bin/cli.js = node_modules/webpack-cli/bin/cli.js = node_modules/webpack-cli/bin/cli.js Once in a while. Ok comes to the file itself
// node_modules/webpack-cli/bin/cli.js
#!/usr/bin/env node
'use strict';
const Module = require('module');
const originalModuleCompile = Module.prototype._compile;
require('v8-compile-cache');
const runCLI = require('.. /lib/bootstrap');
const utils = require('.. /lib/utils');
if(! process.env.WEBPACK_CLI_SKIP_IMPORT_LOCAL) {// Ignore it for now
}
process.title = 'webpack';
if (utils.packageExists('webpack')) {
runCLI(process.argv, originalModuleCompile);
} else {
If webpack is not installed, install it first and then run runCLI
}
Copy the code
Here will be two strange external friends Module,v8-compile-cache let’s see what is used
- Module
Module.exports = *** Node.exports = CommonJs node.exports = *** Node.exports = CommonJs
And we didn’t find anything aboutprototype._compile
After a search of mineRuan Yifeng big blog(Thank you very much!) Provide an environment for the content in our JS module to be executed and compiled.
- v8-compile-cache
The current library provides a hook for require, then uses V8 to cache the code and shorten the instantiation time, which looks like an optimization.
Back to execution, the critical path function is still runCLI(…). First, we focus on the two parameters, one is the unknown friend we have just learned about, and the other is our command line argument list process.argv
So let’s look at runCli(…) What happened in there
// node_modules/webpack-cli/lib/bootstrap.js
const WebpackCLI = require('./webpack-cli');
const utils = require('./utils');
const runCLI = async (args, originalModuleCompile) => {
try {
// Create a new instance of the CLI object
const cli = new WebpackCLI();
cli._originalModuleCompile = originalModuleCompile;
await cli.run(args);
} catch (error) {
utils.logger.error(error);
process.exit(2); }};module.exports = runCLI;
Copy the code
We found runCli(…) We instantiate webpack-cli, give it the technical compiler execution module parameters, and finally execute the inside of the run method ~. The next one is coming very soon and we’re going to start by integrating what we’ve seen so far into our previous picture. Thank you for watching and we’ll continue to see what’s going on in the next one.
To jump to the next post: click here