We’ve covered the basics of a packer, but today we’ll cover WebPack in more detail.

It is divided into the following parts

  • concept
  • The basic use
  • Source code for the debug
  • Implement a simple packer
  • Advanced usage
  • Secondary development

1 the concept

Before introducing WebPack, let’s look at some of the concepts

  • Entry specifies the entry file from which dependencies are recursively resolved when packaging, generating a Dependency graph that represents dependencies between modules
  • Output Specifies the output directory of the packaged file
  • Loaders Webpack itself can only process JS and JSON. If you want to process other files, you need to use the corresponding Loader to convert them into valid modules before adding them to the dependency graph
  • The plugin is used for processing work outside of the Loader
  • Mode Sets the current packaging mode, automatically infuses environment variables, and automatically enables related optimizations
  • The Target WebPack packs node – and Web-side files, and sets the target to use the API for your particular environment
  • Asset is a generic name for various types of files that are introduced in HTML files, such as CSS, images, and so on
  • Bundle The packaged final file
  • Bundle splitting/code Splitting splits the bundles that an app ends up generating into multiple bundles, which can take advantage of caching and load on demand
  • Chunk is an intermediate form of bundle generation. It represents the dependency relationship between modules. There are two types of chunk
    • Initial indicates the dependency specified by the entry file, with filename specifying the name
    • Non-initial Specifies the name of a bundle that is dynamically loaded or split out using SplitChunksPlugin for lazy loading
  • The Manifest is used by the Runtime to parse and load individual packaged modules when the bundle is run in the browser
  • Remove unwanted code when tree Shaking is packaged
  • Config specifies the configuration file in which WebPack works

2 Basic Usage

As a packer, let’s go over the basics,

  1. Prepare an empty folder and executenpm init -yInitialize package.json and download the package we need, we use YARN here, package manager referencehere
    • Webpack Webpack core file
    • Webpack – CLI A tool that invokes the Webpack API using the command line
    yarn add webpack webpack-cli --dev
    Copy the code
  2. Create a SRC folder and create an index.js file
import { log } from "./print";
log(3);
Copy the code

Create a dependent file print.js in the current folder

export const log = (v) => {
  console.log(v);
};
Copy the code
  1. Perform webpack to pack our first file, if there is no configuration file default entry issrc/indexThe output bundle file isdist/main.jsIs invoked from the command linenpx webpackOr you can configure script in package.json file, see the latter for detailsTask-runner.

At this point we have a packaged file called main.js in the dist folder, which can be used directly if we create an HTML file using script import.

(()=>{"use strict"; console.log(3)})();Copy the code

This is the simplest way to use a wrapper, where the SRC two files are modules and main.js is the bundle.

3 source the debug

Want to know the implementation principle of course to see the source code, go

Debug the webpack version 5.21.2. Debug the Webpack version 5.21.2

  • Open Chrome in Chrome ://inspect
  • Execute in the project root directorynode --inspect-brk ./node_modules/webpack/bin/webpack.js, click the link in the red box below to enter the debug mode

Specific implementation details of their own step by step debugging, here is a general introduction to the operation. When executing a package command from the command line, for example, webpack, we will look for the package.json “bin” field in the global installation directory of the corresponding package and execute the corresponding file. If we want to execute the package command in the current project, Use the full directory or use NPX as a helper. So when we are in the foregoing the debug command is actually executed node_modules/webpack/bin/webpack. The contents of the js, this is also our entrance to the debug file.

  1. Execute startup file

To start, check whether webpack-cli is installed, if not, otherwise execute the bin file in webpack-cli, that is node_modules/webpack-cli/bin/cli.js

  1. Synthesis of configuration

Before formal packaging, read relevant configuration files, including but not limited to webpack.config.json, read the parameters when the command is started, and add other default parameters to form the final parameters

  1. Call webpack API

This step is the core of Webpack. Call the webpack() method to create the instantiated Compiler. A Compiler represents the start of webpack and is mainly responsible for the preparation before compilation and the output of the compiled file. The most important thing is that a compilation object is instantiated for the actual compilation. When started in Watch mode, the Compiler object instantiates a new compilation object every time the file is modified. Webpack uses Tapable to mount a number of hooks at various stages of compilation, and at various stages we can use plug-ins to access compiler, and further access compilation and other objects to perform the operations we want. The whole compilation process can be roughly divided into the following steps

  • callcreateCompiler()Instantiate the Compiler and mount the plug-in in the configuration file
  • The Compiler’s run method is executed to instantiate NormalModuleFactory and ContextModuleFactory objects, and to obtain the parameters of the instantiation compilation, such as resolving the loaders configuration
  • callcreateCompilation()Instantiate the compilation object to perform compilation
    • Use loader to convert files from import files
    • Parse the processed code into an AST for further processing, such as changing the require in the source code to __webpack_require__
    • Regenerate the source code and generate the dependency diagram
  • The compiler performsemitAssets()Output the compiled code

Implement a simple packer

Assuming that you have debugged the source code, we will now implement the basic functions of the packer to better understand the principles. Ideas as follows

  • Copy a configuration file as the configuration file for our new packer
  • The startup file of the packer is a JS file that instantiates the compiler in our packer and starts it by calling the run method
  • Implement a Compiler class, initialize various hooks, register plug-ins, initialize compilation objects, output files.
  • Implement a compilation class, starting from the entry file recursive traversal, using loader to process the file and then compile into ast for further processing, and then

Implementation details

  • When compiling, the dependencies are recursively traversed. To prevent repeated traversal, you need to set up a moduleMap to store traversed files
  • For loader, we will use Babel to process the source code and convert other module syntax, such as import to require, to facilitate subsequent processing. For details of using Babel as a compiler, please refer to here
  • For plug-ins, we print a log in the relevant hooks
  • For compiling to ast and further processing, we still use Babel
  • For the bundle output, we use the template engine CJS to insert the parsed code into the template, which contains the __webpack_require__ implementation

Specific implementation of the source code here.

5 Advanced use

This section introduces the configuration, usage and principle of WebPack in detail

6 Secondary Development

This section covers development beyond webpack, including

  • library
  • loader
  • plugin

The last two chapters need to be added.