Webpack is a static module packaging tool. When WebPack works with an application, it recursively builds a dependency graph that contains every module the application needs, and then packages those modules into one or more bundles.
Core options:
- Entry portal
- output
- loader
- The plugin plug-in
- Mode Packaging mode
Webpack execution process reference
The whole process
Option (config + shell config) –> addEntry –> addModuleChain & addModuleDependcies –> buildModule –> Compilation. seal processes each chunk, merges, splits, and generates hash –> createAssets & outputAssets –> end
Critical event node
- EntryOption is executed after the Entry configuration item has been processed
- In watchRun listening mode, a plug-in is executed after a new compilation is triggered
- Build-module, mainly calls loader to process source files, generates AST, traverses AST, encounters require\import and other dependencies, creates dependencies and adds them to the dependency array
- After -compile this in the seal phase, each module and chunk is compiled to generate the compiled source code, merged, split, and hash.
- The emit event generates the resource before the output directory.
- After-emit generates resources to the output directory.
Here are a few concepts to be clear about:
- Compiler is different from compilation objects
- Compiler represents the entire WebPack lifecycle from startup to shutdown
- The compilation object represents a compilation process in which new modules become chunks. Modules Records all parsed modules; Chunks record all chunks; Assets record all files to be generated.)
Compilation Process view
- Tapable class
It mainly controls the publishing and subscribing of hook functions (observer mode), the plugin system that controls WebPack, and compiler & Compilation inherit from Tapaple. The Tapable library exposes many different types of hooks
const {
SyncHook,
SyncBailHook,
SyncWaterfallHook,
SyncLoopHook,
AsyncParallelHook,
AsyncParallelBailHook,
AsyncSeriesHook,
AsyncSeriesBailHook,
AsyncSeriesWaterfallHook
} = require("tapable");
Copy the code
The Hook class has several key methods:
- Tap (name, fn) : registers the callback function fn, as long as the current FN code is finished, the Hook will execute the next FN;
- TapAsync (name, fn, callback) : registers a callback function with an asynchronous operation. By calling callback(), the Hook is told that the current FN has completed and the next FN can be executed.
- call(… Args) : execute all callback functions according to the corresponding rules according to the type of Hook;
- Async: indicates that asynchronous operations are supported in callback functions, not the execution rules of callback functions.
- Series: indicates that the execution rules of the callback function are serial, in the same way Parallel indicates Parallel;
So AsyncSeriesHook means that asynchronous operations are supported in callback functions, and all registered callback functions are executed in a serial manner.
Compiler event hooks throughout the process are based on tapable hooks
class Compiler extends Tapable { consturctor(context){ super() this.hooks = { beforeCompile: new AsyncSeriesHook(), compile: new SyncHook(['params']), afterCompile: xxx, enterOption: xxx, // ... Many types of hooks are defined}}}Copy the code
Presented in tapable’s syncHook, this is a typical observer mode
Class SyncHook {consturctor(){this.hooks = []} // Subscribe tap(name, Fn){this.hooks. Push (fn)} // Release call(){this.hooks. arguments)) } } use const hooks1 = new SyncHook() hooks1.tap('hook1', ()=>{}) hooks1.tap('hook2', Hooks1.call ()=>{})Copy the code
Refer to the plug-in writing method, you can understandcompiler.hooks.enterOption.tab
.
Different modes to help us introduce plug-ins
FAQ:
1. How does the packaging process relate to the plug-in? Process + tapable.
Brief the process + Tapable
2. Package optimization?
Got it, process to talk about packaging optimization, more clear
- 1. Narrow the file search scope
Rules exclude files that do not need to be processed by babel-loader.
{
rules: [{
test: /\.js$/,
use: {
loader: 'babel-loader'
},
// exclude: /node_modules/,
include: [path.resolve(__dirname, 'src')]
}]
}
Copy the code
Reference third-party libraries (JQ, ChartJS) are not parsed or converted.
module: {
//noParse: /jquery|lodash|chartjs/,
noParse: function(content){
return /jquery|lodash|chartjs/.test(content)
}
}
Copy the code
Alias, like @@utils, etc
Resolve.modules tells Webpack to find references and reduce business-side.. /.. / use of xx. Example: path.resolve(__dirname, “SRC “)
Use the Extensions field to tell WebPack, import the module, automatically insert the suffix to try to match the corresponding file, and reduce traversal. Best to import files in code, try to put the suffix with, to avoid lookup.
resolve: {
extensions: ['.js', '.json']
}
Copy the code
- Reduce packaging
1, advance the CommonsChunkPlugin for webpack 3, SplitChunksPlugin for WebPack 4
Use tree-shaking to remove useless code. (Preset, any module type will be compiled to Commonjs by default)
3. The third-party library is transformed into CDN image into VUE, Common and business JS.
4. Use third-party libraries to also look for versions of ES modules, tree-shaking
- 3, caching,
Cache-loader Cache of loader
{
test: /\.js/,
use: [
{
loader: 'cache-loader'
},
{
loader: "babel-loader",
},
],
}
{
test: /\.js/,
use: [
{
loader: "babel-loader",
options: {
cacheDirectory: true
}
},
],
}
Copy the code
HardSourceWebpackPlugin can also provide caching capabilities for modules.
plugins: [
new HardSourceWebpackPlugin()
]
Copy the code
- 4. Multiple processes
Thread-loader happypack implements multi-process processing, but the actual effect is not obvious.
3. New part of webpack5?
- 1, persistent cache, long-term cache, improve build performance.
- 2, better tree-shaking, reduce volume.
- 3. No longer reference Polyfills automatically for Node.js modules, reducing volume.
4. How to write a plugin
class Plugin{
apply(compiler){
}
}
Copy the code
- Life cycle node for Webpack
5. Webpack is vite
Vite principle
- When declaring a script tag of type module
<script type="module" src="/src/main.js"></script>
Copy the code
- The browser will initiate a GET like the server
http://localhost:3000/src/main.js request main. Js file: / / / SRC/main js: import { createApp } from 'vue' import App from './App.vue' createApp(App).mount('#app')Copy the code
- When the browser requests the main.js file and detects that it contains the package imported by import, it sends an HTTP request to its internal import reference to obtain the content file of the module
Such as the GET http://localhost:3000/@modules/vue.js GET http://localhost:3000/src/App.vue
vite
By hijacking these requests from the browser and processing them on the back end, the files used in the project are simply decomposed and consolidated and then returned to the browser.Vite does not package and compile files throughout the processSo it runs much faster than the original WebPack compiler!
Vite faults:
- Ecological inferior to WebAPck; Webpack is very rich in loaders and plugins
- Prod environment build, currently using rollup; The reason is that ESBuild isn’t very CSS and code splitting friendly
- It hasn’t been used on a large scale, and many of the problems or appeals haven’t really been exposed
Vite vs. Webpack
Learning links:
webpack
tapable
Simplified example of mini-pack
webpack-5-release