The words written in the front
In the process of reading Webpack 4.x source code, reference to the “Simple webpack” book and many great god’s article, combined with their own experience, summarized as follows.
An overview
Webpack is like a production line that goes through a series of processes to convert source files into output. Each process on this production line has a single responsibility. There are dependencies between multiple processes. Only after the current process is completed can the next process be handled. A plug-in is like a function that plugs into a production line and works with resources on the production line at a specific time. Webpack organizes this complex production line through Tapable. Webpack broadcasts events as it runs, and the plug-in only needs to listen for the events it cares about to join the production line and change how the production line works. Webpack’s event flow mechanism ensures the orderliness of plug-ins and makes the whole system very extensible. — Wu Haolin, “Simple Webpack”
Core concepts
Entry, loader, Plugin, Module, chunk, no matter documents or related introduction are many, do not repeat, there is a question of the document.
The build process
The running flow of WebPack is a sequential process, from start to finish:
- Initialization parameters: from the configuration file and
Shell
Statement read and merge parameters, get the final parameter; - Start compiling: Initialize with the parameters obtained in the previous step
Compiler
Object, loads all configured plug-ins, executes the object’srun
Method starts compiling; - Identify entry: Locate all entry files according to the entry in the configuration
- Module compilation: Starting from the entry file, call all configured Loader to translate the module, find out the module that the module depends on, and then recurse this step until all the entry dependent files have gone through this step;
- Complete module compilation: After using Loader to translate all modules in step 4, obtain the final content of each module after translation and the dependencies between them;
- Output resources: Assembled into modules based on the dependencies between entry and module
Chunk
And then put eachChunk
Convert to a separate file and add it to the output list. This step is the last chance to modify the output. - Output complete: After determining the output content, determine the output path and file name based on the configuration, and write the file content to the file system. In the process above,
webpack
A specific event is broadcast at a specific point in time, and the plug-in executes specific logic when it listens for an event of interest, which the plug-in can callwebpack
API changes providedwebpack
Run result of.
Compare the two core objects in webpack
Compile
Object: responsible for file listening and starting compilation.Compiler
Example contains the completewebpack
Configuration, global only oneCompiler
Instance.compilation
Object: whenwebpack
Run in development mode, every time a file change is detected, a new oneCompilation
Will be created. aCompilation
Object contains the current module resources, build resources, changing files, and so on.Compilation
Object also provides many event callbacks for plug-ins to extend.- Both objects inherit fromTapable. In order to
Compile
As an example
const {
Tapable,
SyncHook,
SyncBailHook,
AsyncParallelHook,
AsyncSeriesHook
} = require("tapable");
class Compiler extends Tapable {
constructor(context) {
super();
this.hooks = {
/** @type{SyncBailHook<Compilation>} */ / All the files that need to be exported have been generated, asking the plug-in which files need to be exported and which files do not need to be exported. shouldEmit: new SyncBailHook(["compilation"], / * * @)type{AsyncSeriesHook<Stats>} */ / successfully complete a completed compilation and output process.done: new AsyncSeriesHook(["stats"], / * * @)type {AsyncSeriesHook<>} */
additionalPass: new AsyncSeriesHook([]),
/** @type {AsyncSeriesHook<Compiler>} */
beforeRun: new AsyncSeriesHook(["compiler"], / * * @)type{AsyncSeriesHook<Compiler>} */ / Run: new AsyncSeriesHook(["compiler"], / * * @)type{AsyncSeriesHook<Compilation>} */ / After determining which files to output, execute the file output. You can obtain and modify the output here. emit: new AsyncSeriesHook(["compilation"], / * * @)type{AsyncSeriesHook<Compilation>} */ /"compilation"], // All the above events (except run, beforerun) are output events /** @typeThisCompilation: new SyncHook([CompilationParams>}"compilation"."params"], / * * @)type{SyncHook<Compilation, CompilationParams>}"compilation"."params"], / * * @)type{SyncHook<NormalModuleFactory>} */ // The compilation of NormalModuleFactory parameters: new SyncHook(["normalModuleFactory"], / * * @)type{SyncHook<ContextModuleFactory>} */ // Compilation: ContextModuleFactory: new SyncHook(["contextModulefactory"], / * * @)type {AsyncSeriesHook<CompilationParams>} */
beforeCompile: new AsyncSeriesHook(["params"], / * * @)type{SyncHook<CompilationParams>} */ / The compiler object compile: new SyncHook([compiler object compile: new SyncHook(])"params"], / * * @)type{AsyncParallelHook<Compilation>} */ / A new Compilation is created, which is to read files from Entry, compile files according to the file type and configuration of the Loader, and then find the files that the file depends on. Recursive compilation and parsing. make: new AsyncParallelHook(["compilation"], / * * @)type{AsyncSeriesHook<Compilation>} * compile: new AsyncSeriesHook(["compilation"], / * * @)type{AsyncSeriesHook<Compiler>} */ / watchRun: new AsyncSeriesHook(["compiler"], / * * @)type {SyncHook<Error>} */
failed: new SyncHook(["error"], / * * @)type {SyncHook<string, string>} */
invalid: new SyncHook(["filename"."changeTime"], / * * @)type{SyncHook} */ / watchClose: new SyncHook([]), // TODO the following hooks are weirdly located here // TODO move themfor webpack 5
/** @type{SyncHook} */ / initialization phase: Start applying node.js-style file systems to compiler objects to facilitate subsequent file finding and reading. environment: new SyncHook([]), /** @typeAfterEnvironment: new SyncHook([]), /** @type{SyncHook<Compiler>} */ // afterPlugins: new SyncHook([)"compiler"], / * * @)type {SyncHook<Compiler>} */
afterResolvers: new SyncHook(["compiler"], / * * @)type{SyncBailHook<string, EntryOptions>} */ / instantiate an EntryPlugin for each Entry to prepare for recursive parsing of the Entry. entryOption: new SyncBailHook(["context"."entry"])};Copy the code
During WebPack execution, a sequence of events is broadcast — a sequence of events in this.hooks (similar to the life cycle in our usual framework), in which order the subscribers to these events are organized, executed, parameter passed… That’s what Tapable does. I would like to recommend a popular science article about Tapable
Process details
Refer to my comments in the referenced Compile object for details of the process, one thing to note is that the order in which the author hooks write is not the order in which they are called. There are several cases of uncommented ones:
- Less important, or known by event name and context
- I don’t know for the time being.
- Of course the most important events basically covered here are supplemented by a large figure from the reference article
Compilation Process Introduction
A compilation is actually a process of calling the corresponding loader to process files to generate chunks and optimize them. Several key events (in the Compilation object this.hooks) :
buildModule
Use the correspondingLoader
To convert a module;normalModuleLoader
In the useLoader
After converting a module, useacorn
Parses the transformed content and outputs the corresponding abstract syntax tree (AST) for conveniencewebpack
Post-code analysis.seal
All modules and their dependent modules passLoader
After the transformation is complete, the generation begins based on the dependenciesChunk
.
Finally, a picture is taken from the reference article for a clearer understanding of the whole process
reference
- Taobaofed.org/blog/2016/0…
- Imweb. IO/topic / 5 baca…
- Simple Webpack
Spread the word
This article is published in Front of Mint Weekly. Welcome to Watch & Star.