Preface
As mentioned above, webpack
prepared the parameters, and it is time to create the compiler
object.
After creation, it will execute compiler.run
to start compiling. This article will explain the process from new Compiler
to compiler.run()
The whole process takes place in the function body createCompiler
/**
* @param {WebpackOptions} rawOptions options object
* @returns {Compiler} a compiler
*/
const createCompiler = rawOptions => {
new Compiler
Before new, webpack will complete the initialization of the basic parameters, here only the log output format and context are assigned.
applyWebpackOptionsBaseDefaults(options);
webpack/lib/Compiler.js
is the core process of compiling the entire webpack.new Compiler
, first register a bunch of hooksTapable
watch-run , run , before-run , and so on. More hooks can be here at .
Initialization file operation
new NodeEnvironmentPlugin({
infrastructureLogging: options.infrastructureLogging
}).apply(compiler);
Here is the expansion of the compiler object, adding some operations on the file, such as input,
output,
monitoring,
caching and other methods. At the same time, a callback for the
beforeRun
apply(compiler) {
const { infrastructureLogging } = this.options;
compiler.infrastructureLogger = createConsoleLogger({
level: infrastructureLogging.level || "info",
debug: infrastructureLogging.debug || false,
console:
infrastructureLogging.console ||
nodeConsole({
colors: infrastructureLogging.colors,
appendOnly: infrastructureLogging.appendOnly,
stream: infrastructureLogging.stream
})
});
compiler.inputFileSystem = new CachedInputFileSystem(fs, 60000);
const inputFileSystem = compiler.inputFileSystem;
compiler.outputFileSystem = fs;
compiler.intermediateFileSystem = fs;
compiler.watchFileSystem = new NodeWatchFileSystem(
compiler.inputFileSystem
);
compiler.hooks.beforeRun.tap("NodeEnvironmentPlugin", compiler => {
if (compiler.inputFileSystem === inputFileSystem) {
compiler.fsStartTime = Date.now();
inputFileSystem.purge();
}
});
}
The fs here is not the file system of nodejs, it uses a third-party package graceful-fs
Register the plugin
if (Array.isArray(options.plugins)) {
for (const plugin of options.plugins) {
if (typeof plugin === "function") {
plugin.call(compiler, compiler);
} else {
plugin.apply(compiler);
}
}
}
Next, webpack will register all plug-ins registered by options. compiler
object to the plug-in for internal use. The plug-in can register the hook's callback function in the entire compilation process compiler
At the same time, some compiler
hooks pass in the compilation
compilation
hook callback can be registered when the resource is constructed.
environment ready
After the plug-in is registered, webpack assigns default parameters to options again. Why is it with the previous applyWebpackOptionsBaseDefaults
?
Called here
applyWebpackOptionsDefaults(options);
Added another wave of default values.
After the addition, the two hooks environment
and afterEnvironment
compiler.hooks.environment.call();
compiler.hooks.afterEnvironment.call();
Register the built-in plugin
After the environment is initialized, webpack also needs to execute its own internal default plugin.
new WebpackOptionsApply().process(options, compiler);
Here, the corresponding plug-in will be executed according to your configuration.
Pick a few things that have something to do with hooks,
Parse entry
new EntryOptionPlugin().apply(compiler);
compiler.hooks.entryOption.call(options.context, options.entry);
Here is the entry data structure needed to generate the build
/** @type {EntryOptions} */
const options = {
name,
filename: desc.filename,
runtime: desc.runtime,
layer: desc.layer,
dependOn: desc.dependOn,
publicPath: desc.publicPath,
chunkLoading: desc.chunkLoading,
wasmLoading: desc.wasmLoading,
library: desc.library
};
Then call EntryPlugin
to register the Compiler.hooks:compilation, make hook functions in the applay
In the future, when the make
hook is compiler
object, the callback registered EntryPlugin
complition.addEntry(context, dep, options)
start compilation
This is the key point, otherwise the entrance to the beginning cannot be found
compiler.hooks.make.tapAsync("EntryPlugin", (compilation, callback) => {
compilation.addEntry(context, dep, options, err => {
callback(err);
});
}
);
Register the resloverFactory hook
After some of the plugins of webpack itself are called, the hook afterPlugin
compiler.hooks.afterPlugins.call(compiler);
Next, webpack registered the resolveOptions
hook on compiler.resolverFactory
compiler.resolverFactory.hooks.resolveOptions
.for("normal")
.tap("WebpackOptionsApply", resolveOptions => {
resolveOptions = cleverMerge(options.resolve, resolveOptions);
resolveOptions.fileSystem = compiler.inputFileSystem;
return resolveOptions;
});
compiler.resolverFactory.hooks.resolveOptions
.for("context")
.tap("WebpackOptionsApply", resolveOptions => {
resolveOptions = cleverMerge(options.resolve, resolveOptions);
resolveOptions.fileSystem = compiler.inputFileSystem;
resolveOptions.resolveToContext = true;
return resolveOptions;
});
compiler.resolverFactory.hooks.resolveOptions
.for("loader")
.tap("WebpackOptionsApply", resolveOptions => {
resolveOptions = cleverMerge(options.resolveLoader, resolveOptions);
resolveOptions.fileSystem = compiler.inputFileSystem;
return resolveOptions;
});
The purpose here is to Factory.createResolver
(containing the relevant resolve project configuration items).
Then call the afterResolvers
hook
compiler.hooks.afterResolvers.call(compiler);
loading finished
So far, there are enough things on the compiler object to start our compilation, and we will tell the outside world that the initialization is complete. With the tonality of webpack, there must be a hook trigger.
compiler.hooks.initialize.call();
Concluding remarks
All the things before webpack compilation have been explained clearly, the next article will start the compilation.
Please note the registration of various hooks mentioned in the article. In the subsequent compilation process, some of the hooks registered before will often be triggered in the places you missed. This is also a pain point in the process of debugging webpack.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。