In the first two basic and advanced configuration, we learned how to build pack configuration Webpack to achieve different purposes, including frequent mention of the entry, loader, the plugin, the module, the chunk, bundle nouns, such as what they are? What are the differences and connections?
The module, the chunk and bundle
Webpack is described on the website as follows:
Webpack is a static module packaging tool for modern JavaScript applications. When WebPack works with an application, it internally builds a dependency graph that maps to each module required for the project and generates one or more bundles.
We can also see a picture on the homepage of the official website to illustrate the role of Webpack:And we can see that in this picturemodule
.chunk
andbundle
The difference and connection between:
- The left-hand side of the equation can be interpreted as
module
, it isIndividual source files.In the world of Webpack, everything is modular, anything that can be referenced is a module. - The middle part is
chunk
.A combination of multiple modules, such as:entry
.import()
.splitChunk
And so on.chunk
Do dependency analysis. - The right-hand side is
bundle
, i.e.,The final output file.
The structure of the Webpack
Let’s take a look at the complete structure of the configuration object output from the Webpack configuration file:
|-- webpack.config.js
|-- entry Define the entry to build the dependency graph
|-- output Define the name and location of the output bundle
|-- module # define loader
|-- plugins # define plug-in
|-- mode Select develop or build mode
|-- devServer The development environment starts the service
|-- optimization Configure optimization items manually
Copy the code
Entry (entrance)
Entry Point __ indicates which module WebPack should use as a starting point for building its internal dependency graph. Once at the entry point, WebPack finds out which modules and libraries are (directly and indirectly) dependent on the entry point. In the previous two sections, you can configure entry in two ways:
Single entry
Usage: entry: string | [string]
module.exports = {
entry: './path/to/my/entry/file.js'
};
Copy the code
Multiple entry
Usage: entry: {< entryChunkName > string | [string]} | {} each pair of key/value pair is a separate entrance, the separation of independent dependency graph, thus can make a difference in the chunk.
module.exports = {
entry: {
app: './src/app.js'.adminApp: './src/adminApp.js'}};Copy the code
Why do you need multiple entrances?
If our program is a multi-page program, we need to configure multiple entries in Webpack. In a multi-page application, the server pulls a new HTML document to the client. The page reloads the new document, and the resource is re-downloaded. However, use optimization.splitchunks to create bundles for application code shared between pages. Due to the increasing number of entry points, multi-page applications can reuse large amounts of code/modules between multiple entry points, which can greatly reduce the amount of duplicate code and the volume of the final package.
The output (output)
The Output attribute tells WebPack where to export the bundles it creates and how to name those files. Note that even though more than one entry starting point can exist, only one output configuration can be specified.
Single entry
module.exports = {
output: {
filename: 'bundle.js',}};Copy the code
This configuration outputs a single bundle.js file to the dist directory.
Multiple entry
If more than one chunk is created in the configuration, placeholders should be used to ensure that each file has a unique name.
module.exports = {
entry: {
app: './src/app.js'.search: './src/search.js'
},
output: {
filename: '[name].js'.path: __dirname + '/dist'}};Copy the code
loader
Webpack only understands JavaScript and JSON files. Loader enables WebPack to process other types of files and convert them into valid modules for use by applications and to be added to dependency diagrams. In the webpack configuration, loader has two properties:
test
: Identifies which files will be converted.use
: defines which loader should be used during conversion.
module.exports = {
module: {
rules: [{test: /\.css$/, use: 'css-loader' },
{ test: /\.ts$/, use: 'ts-loader'}}};Copy the code
The plugin (plug-in)
Loaders are used to transform certain types of modules, while plug-ins can be used to perform a wider range of tasks. Including: package optimization, resource management, injection of environment variables. Plug-ins are designed to solve other things that loader cannot implement. To use a plug-in, simply require() it and add it to the plugins array. Most plug-ins can be customized with options. You can also use the same plug-in multiple times in a configuration file for different purposes, creating an instance of the plug-in by using the new operator.
onst HtmlWebpackPlugin = require('html-webpack-plugin'); // Install via NPM
const webpack = require('webpack'); // Used to access built-in plug-ins
module.exports = {
module: {
rules: [{test: /\.txt$/, use: 'raw-loader'}},plugins: [
new HtmlWebpackPlugin({template: './src/index.html'}})];Copy the code
The principle of the author
The Webpack plug-in is a JavaScript object with the Apply method. The Apply method is called by the Webpack Compiler and the Compiler object is accessible throughout the compile life cycle. ConsoleLogOnBuildWebpackPlugin.js:
const pluginName = 'ConsoleLogOnBuildWebpackPlugin';
class ConsoleLogOnBuildWebpackPlugin {
apply(compiler) {
compiler.hooks.run.tap(pluginName, compilation= > {
console.log('Webpack build process begins! '); }); }}module.exports = ConsoleLogOnBuildWebpackPlugin;
Copy the code
Mode (mode)
Setting the mode parameter by selecting one of development, Production, or None enables the optimization built into WebPack for that environment. The default value is production. Usage: string = ‘production’ : ‘none’ | ‘development’ | ‘production’
model | function |
---|---|
development |
willDefinePlugin 中 process.env.NODE_ENV Is set todevelopment Is the module andchunk Enable a valid name. |
production |
willDefinePlugin 中 process.env.NODE_ENV Is set toproduction . For the module andchunk Enable deterministic obfuscated names,FlagDependencyUsagePlugin .FlagIncludedChunksPlugin .ModuleConcatenationPlugin .NoEmitOnErrorsPlugin 和 TerserPlugin 。 |
none |
Do not use any default optimization options |
Optimization (optimization)
Starting with WebPack 4, different optimizations will be performed depending on the mode you choose, but all optimizations can be manually configured and rewritten. Let’s take a look at the optimization related plugins that we used for the configuration in the previous two sections.
Minimizer (compressed)
Output code is compressed by providing one or more custom TerserPlugin instances that override the default compression tool (Minimizer). [TerserPlugin] or [function (compiler)]
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
JS / / compression
new TerserPlugin({
cache: true.parallel: true.sourceMap: true.// If source-maps is used in production, it must be set to true
terserOptions: {
// https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions}}),/ / compress CSS
new OptimizeCSSAssetsPlugin({}),
],
}
};
Copy the code
splitChunks
Prior to Webpack 4, chunks were connected via dependency maps, using the CommonsChunkPlugin to avoid overlapping chunks of dependency, but there was no other way to optimize them further. After Webpack 4, CommonsChunkPlugin was removed and replaced with Optimization.splitchunks to customize the fragmentation of code blocks to achieve finer fragmentation and reuse and better load on demand.
The default value
Webpack will automatically split chunks based on the following criteria:
- New blocks can be shared, or modules can come from the node_modules folder
- New block >= 20KB (before min + gz)
- When loading blocks on demand, the maximum number of parallel requests is <= 30
- The maximum number of parallel requests at initial page loading is <= 30
The custom
Let’s review the configuration of optimization.splitchunks in the previous two sections:
chunks
: Selects which blocks to optimize
Values: string = ‘all’ | ‘async’ | ‘initial’
'async'
: asynchronous chunk. Only files that are imported asynchronously are processed'initial'
: chunk. Files that are imported asynchronously are not processed'all'
: Blocks can also be shared between asynchronous and non-asynchronous blocks
cacheGroups
: Cache grouping
The cacheGroups structure is an object where each attribute corresponds to a configuration of a chunk. The key is the name of the chunk.
name
:chunk
The name of thepriority
: A module can belong to more than one cache group, and optimization will preferentially select the cache group with the highest cache grouppriority
, the higher the value, the higher the prioritytest
: controls the module selection for this cache group, omitting it selects all modules. It can match absolute module resource paths or block names. When a block name is matched, all modules in the block are selectedminSize
: Size limit of the moduleminChunks
: The minimum number of module reuse times. Only the value greater than or equal to this value will be extracted
module.exports = {
optimization: {
// Split code blocks
splitChunks: {
chunks: 'all'.// Cache grouping
cacheGroups: {
// Third party module
vendor: {
name: 'vendor'./ / the chunk name
priority: 1.// The permission is higher
test: /node_modules/,
minSize: 0.// Size limit
minChunks: 1 // At least several times
},
// Public module
common: {
name: 'common'./ / the chunk name
priority: 0./ / priority
minSize: 0.// Public module size limit
minChunks: 2 // The public module has been reused at least several times}}}}};Copy the code