How do I automatically add bundles generated at build time to HTML
Using the HtmlWebpackPlugin, a new index.html file will be generated to replace our original file.
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: './src/index.js',
print: './src/print.js',
},
plugins: [
new HtmlWebpackPlugin({
title: 'Output Management',
}),
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
Copy the code
How to clean up (webPack-generated files are placed in)/dist
folder
Webpack generates files and places them in the /dist folder, but it doesn’t keep track of which files are actually used in the project.
Use the clean-webpack-plugin to clean up the /dist folder before each build so that only the files used are generated.
How do I map compiled code back to the original source
When Webpack packages source code, it can be difficult to trace the original locations of Errors and warnings in the source code.
To make it easier to track errors and warnings, JavaScript provides source maps that map compiled code back to the original source code.
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); Module.exports = {// Note: Source map is resource-intensive for development environments only. // Avoid inline-*** and eval-*** in production because they increase bundle size and reduce overall performance: 'development', entry: { index: './src/index.js', print: './src/print.js', }, devtool: 'inline-source-map', plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: 'Development', }), ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist'), }, };Copy the code
How do I automatically compile code after it changes
Webpack provides the following methods:
webpack --watch
Command line (Watch modewatch mode
)
Disadvantages: You need to manually refresh the browser to see the actual effect of the modification
webpack serve --open
The command line,webpack-dev-server
)
Webpack-dev-server provides a simple Web server with live reloading
Note: Webpack-dev-server is not written to any output files after compilation. Instead, you keep the bundle files in memory and then serve them to the server as if they were real files mounted on the server root path. If your page wants to find the bundle files in a different path, you can change this using the publicPath option in the Dev Server configuration.
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { mode: 'development', entry: { index: './src/index.js', print: './src/print.js', }, devtool: 'inline-source-map', devServer: {contentBase: './dist',// from where to find file serve}, [ new CleanWebpackPlugin({ cleanStaleWebpackAssets: false }), new HtmlWebpackPlugin({ title: 'Development', }), ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist'), }, };Copy the code
- use
webpack-dev-middleware
Webpack-dev-middleware is a wrapper that sends webPack-processed files to a server.
Webpack-dev-server uses it internally, but it can also be used as a separate package for more customization as needed.
Can be used in combination with ExpressJS (custom setup server), etc
You’ll need to manually refresh your browser to see the changes in action, and use the Webpack-hot-Middleware dependency package to enable HMR on your custom server or application
server.js
const express = require('express'); const webpack = require('webpack'); const webpackDevMiddleware = require('webpack-dev-middleware'); const app = express(); const config = require('./webpack.config.js'); const compiler = webpack(config); // Tell Express to use webpack-dev-middleware, // and use the webpack.config.js configuration file as the base configuration. app.use( webpackDevMiddleware(compiler, { publicPath: config.output.publicPath, }) ); // Serve the file to port 3000. app.listen(3000, function () { console.log('Example app listening on port 3000! \n'); });Copy the code
Method of code separation
-
Entrance to the starting point
Disadvantages:
- Multiple Manual configurations
- If the entry chunks contain duplicate modules, those duplicate modules are introduced into each bundle.
- This approach is not flexible and does not dynamically separate the code from the core application logic
- To prevent the repeat
- Entrance to rely on
Configure the dependOnoption option so that modules can be shared between chunks
const path = require('path'); module.exports = { mode: 'development', entry: { index: { import: './src/index.js', dependOn: 'shared', }, another: { import: './src/another-module.js', dependOn: 'shared', }, shared: 'lodash', }, output: { filename: '[name]. Bundle. Js, path: the path. The resolve (__dirname,' dist),}, / / note: to be used on an HTML page is required for a multiple entry set optimization. RuntimeChunk: 'single' to split runtime code into a single chunk optimization: {runtimeChunk: 'single',},};Copy the code
SplitChunksPlugin
The SplitChunksPlugin plug-in can extract a common dependency module into an existing chunk of entry or into a newly generated chunk.
const path = require('path');
module.exports = {
mode: 'development',
entry: {
index: './src/index.js',
print: './src/print.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
optimization: {
splitChunks: {
chunks: 'all',
},
},
};
Copy the code
- Dynamic import
- ECMAScript proposal
import()
grammar(recommended) - Webpack specific
require.ensure
Pay attention to
Import () calls will use promises internally. If you use import() in older browsers (IE 11, for example), remember to use a polyfill library (es6-Promise or promise-polyfill, for example) to implement promises.
Since import() returns a promise, it can be used with async functions.
Prefetch/preload
- Prefetch: Resources that may be required for some future navigation
/ /... import(/* webpackPrefetch: true */ './path/to/LoginModal.js');Copy the code
This generates and appends to the header of the page, indicating that the browser prefetches the login-modal-chunk.js file during idle time.
- Preload: Resources may be required under the current navigation
ChartComponent.js
/ /... import(/* webpackPreload: true */ 'ChartingLibrary');Copy the code
When using ChartComponent in a page, chartComponent.js is requested along with charting-library-chunk. Assuming that page-chunk is large and slow to load, the page will display a LoadingIndicator until the Charting-library-chunk request completes and the LoadingIndicator disappears. Starting requires very little load time because there is only one round trip, not two. Especially in high latency environments.
Note: Improper use of webpackPreload can hurt performance
The preload directive differs from the prefetch directive in a number of ways:
preload
Chunk starts loading in parallel when the parent chunk loads.prefetch
Chunk starts loading after the parent chunk finishes loading.preload
Chunk has a medium priority and is downloaded immediately.prefetch
Chunk downloads while the browser is idle.preload
The chunk will be requested immediately in the parent chunk for the present moment.prefetch
Chunk will be used at some point in the future.- Browser support varies.
Analysis of the bundle
analyse
Official: You can run this command linewebpack --profile --json > stats.json
Generate the required JSON fileswebpack-chart
: WebPack Stats interactive pie chart.webpack-visualizer
Visualize and analyze your bundles to see which modules take up space and which are likely to be reused.webpack-bundle-analyzer
: a plugin and CLI tool that presents bundle content as a convenient, interactive, scalable tree.webpack bundle optimize helper
: This tool analyzes your bundles and provides actionable improvements to reduce their size.bundle-stats
: Generates a bundle report (bundle size, resources, modules) and compares the results between different builds.
The cache
Ensure that files generated by webPack compilation can be cached by the client and that new files can be requested if the file contents change.
const path = require('path'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.js', plugins: [// For v2 versions of the CleanWebpackPlugin, Use new CleanWebpackPlugin(['dist/*']) new CleanWebpackPlugin(), new HtmlWebpackPlugin({title: 'Caching', }), ], output: { filename: '[name].[contenthash].js', path: Resolve (__dirname, 'dist'),}, optimization: {// Resolve vendor bundle changes with its module.id. 'Deterministic ', runtimeChunk: 'single',// Extract the boot template and split the Runtime code into a single chunk splitChunks: CacheGroups: {vendor: {test: {cacheGroups: {vendor: {test: /[\\/]node_modules[\\/]/, name: 'vendors', chunks: 'all', }, }, }, }, };Copy the code
Building performance improvements
-
By using the include field, loader applies only to the module that actually needs to convert it
-
Improve parsing speed
- To reduce
resolve.modules
.resolve.extensions
.resolve.mainFiles
.resolve.descriptionFiles
Because they increase the number of file system calls. - If you don’t use
symlinks
(e.g.npm link
oryarn link
), can be setresolve.symlinks: false
. - If you use custom
resolve plugin
Rule, and not specifiedcontext
Context, which can be setresolve.cacheWithContext: false
- To reduce
-
Use the DllPlugin to generate separate compilation results for code that changes infrequently
-
Try to keep chunks small
- Use less quantity/volume
library
. - Used in multi-page applications
SplitChunksPlugin
. - Used in multi-page applications
SplitChunksPlugin
And openasync
Mode. - Remove unreferenced code.
- Only compile the code you are currently developing.
- Use less quantity/volume
-
Don’t use too many workers
Thread – loaders can be distributed to a worker pool(worker pool).
Note: Don’t use too many workers because node.js runtime and Loader have startup overhead. Minimize module transfers between worker and main process. Inter-process communication (IPC) is very resource-intensive.
-
Persistent cache
-
Removing the ProgressPlugin from the Webpack reduces build time.
-
Minimize the number of preset/ plugins in the project.
-
Use fork-ts-checker-webpack-plugin for type checking in a separate process.
-
Configure the Loader to skip type checking.
-
When ts-Loader is used, happyPackMode: true/transpileOnly: true.
-
There is a bug in Node-sass that blocks threads from the Node.js thread pool. When thread-Loader is used, you need to set workerParallelJobs: 2
How do you configure your development and build environments independently and merge common parts
In a development environment, we need: a powerful source map and a Localhost Server with live reloading or hot Module replacement capabilities.
In production, the goal is to focus on bundle compression, lighter source maps, resource optimizations, and so on to improve load times.
Use the Webpack-merge tool, which references the “common” configuration to avoid repeating code in environment-specific configurations
Resource module
Asset Module is a module type that allows you to use resource files (fonts, ICONS, etc.) without having to configure an additional loader.
Before WebPack 5, it was common to use:
raw-loader
Import the file as a stringurl-loader
Inline the file as a data URI into the bundlefile-loader
Send the file to the output directory
Asset Module Type replaces all of these loaders by adding 4 new module types:
asset/resource
Send a separate file and export the URL. Previously by usingfile-loader
The implementation.asset/inline
Export the data URI of a resource. Previously by usingurl-loader
The implementation.asset/source
Export the source code of the resource. Previously by usingraw-loader
The implementation.asset
Automatically choose between exporting a data URI and sending a separate file. Previously by usingurl-loader
And configure the resource volume limitation implementation.
module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: Path.resolve (__dirname, 'dist'), // Customize the output filename 1. AssetModuleFilename to modify the template string assetModuleFilename: 'images/[hash][ext][query]' }, module: { rules: [ { test: / \. (PNG | JPG | GIF) $/, / / need from asset loader to exclude from new URL processing asset dependency: {not: [' URL ']}, use: [{loader: 'url-loader', options: {limit: 8192,}},], // Want to stop processing of the current asset module and start processing again to avoid duplicate asset type: 'javascript/auto'}, // Resource Configuration {test: /\.png/, type: 'asset/resource'}, // Customize the output file name 2. Send some resources to the specified directory. This applies only to asset and asset/resource module types {test: /\.html/, type: 'asset/resource', generator: { filename: 'static/[hash][ext][query]' } }, { test: /\.svg/, type: 'asset/inline', // Custom data URI generator, all.svg files will be encoded with the mini-svG-data-URI package generator: {dataUrl: content => { content = content.toString(); return svgToMiniDataURI(content); } }, { test: /\.txt/, type: 'asset/source', }, { test: /\.doc/, // General resource type, WebPack will automatically choose between resource and inline by default: files smaller than 8KB will be treated as inline module type, otherwise it will be treated as Resource module type: 'asset', parser: { dataUrlCondition: { maxSize: 4 * 1024 // 4kb } } } ] }, }Copy the code
- The resource resources
import mainImage from './images/main.png';
img.src = mainImage; // '/dist/151cfcfa1bd74779aadb.png'
Copy the code
- The inline resources
import metroMap from './images/metro.svg'; block.style.background = `url(${metroMap})`; // url(data:image/svg+xml; base64,PHN2ZyB4bWxucz0iaHR0cDo... vc3ZnPgo=)Copy the code
- The source of resources
src/example.txt
Hello world
Copy the code
src/index.js
import exampleText from './example.txt';
block.textContent = exampleText; // 'Hello world'
Copy the code
- The url resources
Webpack also creates resource modules when using new URL(‘./path/to/asset’, import.meta. URL).
src/index.js
const logo = new URL('./logo.svg', import.meta.url);
Copy the code
Depending on the target in your configuration, Webpack will compile the above code into different results:
// target: web
new URL(__webpack_public_path__ + 'logo.svg', document.baseURI || self.location.href);
// target: webworker
new URL(__webpack_public_path__ + 'logo.svg', self.location);
// target: node, node-webkit, nwjs, electron-main, electron-renderer, electron-preload, async-node
new URL(__webpack_public_path__ + 'logo.svg', require('url').pathToFileUrl(__filename));
Copy the code