build_ Construction process of process webpack

How to build webpack?

1, Operation process

The running process of webpack is a serial process, and its workflow is to connect various plug-ins in series

Events will be broadcast during operation. The plug-in only needs to listen to the events it cares about, and can join this webpack mechanism to change the operation of webpack and make the whole system scalable

The following three steps will be performed from start to finish:

  • Initialization process: read and merge parameters from configuration files and Shell statements, and initialize the required plug-ins and configure the parameters required by the execution environment such as plug-ins
  • Compilation and construction process: send from the Entry, call the corresponding Loader for each Module to translate the file content, find the Module that the Module depends on, and compile recursively
  • Output process: combine the compiled Module into a Chunk, convert the Chunk into a file, and output it to the file system

Initialization process

Read and merge parameters from configuration files and Shell statements to get the final parameters

The configuration file is webpack.com by default config. JS, or specify the configuration file in the form of command, which is mainly used to activate the add ins and plug-ins of webpack

For the content analysis of file configuration, the following notes are given:

var path = require('path');
var node_modules = path.resolve(__dirname, 'node_modules');
var pathToReact = path.resolve(node_modules, 'react/dist/react.min.js');

module.exports = {
  // The entry file is the starting point of module construction, and each entry file corresponds to the last chunk generated.
  entry: './path/to/my/entry/file.js',
  // The file path points to (to speed up the packaging process).
  resolve: {
    alias: {
      'react': pathToReact
    }
  },
  // The generated file is the end point of module construction, including output file and output path.
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: '[name].js'
  },
  // Here, loaders for processing various modules are configured, including css preprocessing loader, es6 compilation loader and image processing loader.
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel',
        query: {
          presets: ['es2015', 'react']
        }
      }
    ],
    noParse: [pathToReact]
  },
  // Each plug-in object of webpack executes the corresponding method in the event flow of webpack.
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ]
};

Webpack will webpack config. Copy the configuration items in JS to the options object and load the plugins configured by the user

After completing the above steps, the Compiler compilation object is initialized. The object controls the webpack declaration cycle and does not perform specific tasks, but only performs some scheduling work

class Compiler extends Tapable {
    constructor(context) {
        super();
        this.hooks = {
            beforeCompile: new AsyncSeriesHook(["params"]),
            compile: new SyncHook(["params"]),
            afterCompile: new AsyncSeriesHook(["compilation"]),
            make: new AsyncParallelHook(["compilation"]),
            entryOption: new SyncBailHook(["context", "entry"])
            // Many different types of hooks are defined
        };
        // ...
    }
}

function webpack(options) {
  var compiler = new Compiler();
  ...// Check options. If the watch field is true, start the watch thread
  return compiler;
}
...

The Compiler object inherits from Tapable and defines many hook functions during initialization

Compile build process

Find all the entry files according to the entry in the configuration

module.exports = {
  entry: './src/file.js'
}

After initialization, the Compiler's run will be called to really start the webpack compilation and construction process. The main process is as follows:

  • compile starts compiling
  • make analyzes modules and their dependent modules from the entry point and creates these module objects
  • Build module
  • seal package construction results
  • emit outputs each chunk to the result file

Compile compile

After executing the run method, compile will be triggered first, mainly to build a Compilation object

This object is the main executor in the compilation stage. It mainly follows the following processes in turn: the object that performs the main tasks such as module creation, dependency collection, blocking, packaging and so on

make compilation module

After completing the above compilation object, start reading from the Entry file, mainly executing_ addModuleChain() function, as follows:

_addModuleChain(context, dependency, onModule, callback) {
   ...
   // Find the corresponding factory function according to the dependency
   const Dep = /** @type {DepConstructor} */ (dependency.constructor);
   const moduleFactory = this.dependencyFactories.get(Dep);
   
   // Call the create of the factory function NormalModuleFactory to generate an empty NormalModule object
   moduleFactory.create({
       dependencies: [dependency]
       ...
   }, (err, module) => {
       ...
       const afterBuild = () => {
        this.processModuleDependencies(module, err => {
         if (err) return callback(err);
         callback(null, module);
           });
    };
       
       this.buildModule(module, false, null, null, err => {
           ...
           afterBuild();
       })
   })
}

The process is as follows:

_ addModuleChain receives the entry dependency passed in by the parameter dependency, and uses the corresponding factory function normalmodulefactory The Create method generates an empty module object

The callback will store this module in compilation Modules object and dependencies Module object will also be stored in compilation. Because it is an entry file In entries

Then execute buildModule to enter the process of real building module module content

build module completes module compilation

Here, we mainly call the configured loaders to convert our module into a standard JS module

After converting a module with Loader, acorn is used to analyze the converted content and output the corresponding abstract syntax tree (AST) to facilitate the analysis of the code later in Webpack

Start from the configured entry module, analyze its AST. When you encounter the require and other imported module statements, add them to the list of dependent modules. At the same time, recursively analyze the newly found dependent modules, and finally find out the dependencies of all modules

Output process

seal output resource

The seal method is mainly to generate chunks, perform a series of optimization operations on chunks, and generate the code to be output

The chunk in webpack can be understood as a module configured in the entry or a module introduced dynamically

According to the dependency between the entry and the module, the chunks containing multiple modules are assembled, and then each Chunk is converted into a separate file and added to the output list

emit output completed

After determining the output content, determine the output path and file name according to the configuration

output: {
    path: path.resolve(__dirname, 'build'),
        filename: '[name].js'
}

Before the Compiler starts generating files, the hook emit will be executed, which is our last chance to modify the final file

Thus, the whole packaging process of webpack is over

Summary

Keywords: node.js Front-end Webpack

Added by wayang_mbeling on Sun, 06 Feb 2022 20:55:55 +0200