preface
A series of notes sorted out in the process of learning Webpack, if there is any wrong place, please guide your elder brother.
What exactly is Webpack for?
Webpack is a packaging tool. What can it do? Here are a few:
- 1. Package your code and remove the parts of your code that you don’t need
- 2, with a variety of
loader
So you can use itSass, less, TS, es
New syntax, and parsing a variety of files - 3, help you through the use of packaged projects
plugin
Do various optimizations (compress, obfuscate code)
Download and basic use of Webpack
Download webpack
NPM install webpack webpack-cli -g
View the Webpack version number
webpack -v
// Create the webpack.config.js file
const { resolve } = require('path');
module.exports = {
entry:"./src/index.js".// Import file
output: {// Output configuration
filename:'./built.js' // Output the file name
path:resolve(__dirname,'build/js') // Output file path configuration
},
mode:"production" // Production environment
}
// Inside any module file, you can use the __dirname variable to get the full absolute path to the directory where the current module file resides.
// index.js entry file configuration
import data from "./data/json"
console.log(data);
function add(x, y){
return x + y;
}
console.log(add(1.2));
Copy the code
Package the file using the Webpack directive
Files and code generated after successful packaging (because production js code is automatically compressed into a single line for display)
Basic conclusions
- 1.
webpack
Can deal withjs/json
Resources,css/img
Resources need to be packaged by downloading proprietary dependencies - 2,
webpack
It is divided into development environment and production environment - 3. Development environment: where your code is tested, changed, and run on a local server,
- Production: Your code is already being used on a real server
Webpack development environment configuration
1. Package style resources
Run the NPM install css-loader style-loader less-loader -d command to install the required dependencies for handling style resources
// Configure it in rules in the module of webpack.config.js
// Loader (style) configuration
module: {rules: [// Details loader configuration
{
// Which files to match
text:/\.css$/.// Which loaders are used for processing
use:[
// Loaders in the use array are executed from right to left or from bottom to top
// Create a style tag, insert the js style resource, add it to the head to take effect
'style-loader'.// Load the CSS file as a comm module as a string into js
'css-loader'] {},text:/\.less$/,
use:[
'style-loader'.'css-loader'.// Compile less files into CSS files
'less-loader']]}}Copy the code
2. Package HTML resources
NPM install html-webpack-plugin -d installs dependencies needed to process HTML files
// Configure the following options in plugins in the webpack.config.js configuration item
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins:[
// Plugins are configured
// html-webpack-plugin
// Function: creates an empty HTML by default, automatically importing all the resources (JS/CSS) that are packaged as output.
// Requirements: Need a structured HTML file
new HTMLWebpackPlugin({
// Copy the "./ SRC /index.html" file and automatically import all the resources (JS/CSS) that are packaged as output.
// title:' This is a custom title'
template:"./src/index.html"})].mode:"development"
Copy the code
3. Pack image (IMG) resources
NPM install url-loader -d installs the dependencies needed to process image files
// Configure it in rules in the module of webpack.config.js
module: {rules:[
{
// Problem: img images in HTML cannot be processed by default
// Process image resources
test:/\.(jpg|png|gif)$/.// Use a loader
loader:"url-loader".options: {// Images smaller than 8KB will be base64 processed
// Advantages: reduce the number of requests (reduce server stress)
// Disadvantages: Larger image size (slower file request)
limit:8 * 1024.// Problem: Because url-loader uses es6 module by default, htMl-loader imports images from commonJS specification
[object,object]
// Resolve: Disable ES6 modularization of urL-loader and use CommonJS parsing
esModule:false.// Turn off es6 module syntax
// Rename the image
// [hash:10] takes the first 10 digits of the hash value of the image
// [ext] takes the original extension of the file
name:'[hash:10].[ext]'
},
Webpack 5 needs to be added
type:'javascript/auto'}}]Copy the code
4. Pack other resources (Iconfont.)
NPM install file-loader -d installs the dependencies needed to process image files
// Configure it in rules in the module of webpack.config.js
// Package other resources (other than HTML/JS/CSS resources)
{
// Exclude CSS /js/ HTML resources
exclude:/\.(css|js|html)$/,
loader:'file-loader'.options: {name:"[hash:10].[ext]"}}Copy the code
5. DevServer
Configure devServer in webpack.config.js
devServer:{
// webpack5
static: {directory: resolve(__dirname,"build")},/ / contentBase: resolve an error (__dirname, "build")
// Start gzip compression
compress: true./ / the port number
port: 3000.// Whether to open the page automatically
open: true,}Copy the code
Purpose: To automate (automatically compile, automatically open the browser, automatically refresh the browser)
Features: Only packages are compiled in memory, with no output
Start command: NPX webpack serve
6. The development environment is configured
const HtmlWebpackPlugin = require('html-webpack-plugin');
const{ resolve } = require('path');
module.exports = {
entry:"./src/js/index/js".output: {filename:"js/built.js".path:resolve(__dirname,'build')},module: {rules: [// Loader handles the configuration of the style
// Process less resources
{
test:/\.less$/,
use:['style-loader'.'css-loader'.'less-loader']},// Process CSS resources
{
test:/\.css$/,
use:['style-loader'.'css-loader']},// Process image resources
{
test:/\.(jpg|png|gif)$/,
loader:"url-loader".options: {// indicates that images below 8KB will be processed through Base64
limit:8 * 1024.name:"[hash:10].[ext]".esModule:false.outputPath:"imgs"
},
type:"javascript/auto"
},
// Process img resources in HTML
{
test:/\.html$/,
loader:"html-loader"
},
{
// Process other resources
exclude:/\.(html|js|css|less|jpg|png|gif)/,
loader:"file-loader".options: {name:"[hash:10].[ext]".outputPath:"media"}}},plugins: [// Plugins are configured
new HtmlWebpackPlugin({
template:"./src/index.html"})].// Development server
devServer: {static: {directory:resolve(__dirname,"build")},compress:ture,
port:3000.open:true
},
mode:"development"
}
Copy the code
Webpack production environment configuration
1. Extract the CSS into a separate file
Install mini-css-extract-plugin -d dependencies required by NPM
const HtmlWebpackPlugin = requrie('html-webpack-plugin')
const MinCssExtractPlugin = requrie('mini-css-extract-plugin')
const { resolve } = require('path')
module.exports = {
entry:"./src/js/index.js".output: {filename:"js/built.js".path:resolve(__dirname,'build')},module: {rules:[
{
test:/\.css$/,
use:[
// Create a style tag to place the style on
// 'style-loader'这个loader取代style-loader
// Function: Extract CSS from js into a separate file
MiniCssExtarctPlugin.loader,
// Integrate CSS files into js files
'css-loader']]}},plugins: [new HtmlWebpackPlugin({
template:"./src/index.html"
}),
new MiniCssExtractPlugin({
// Rename the file
filename:"css/built.css"})].mode:"production"
}
Copy the code
The effect
2. Check the CSS compatibility
Install mini-css-extract-plugin -d dependencies required by NPM
// Add the following configuration when rules handles CSS in the module of webpack.config.js
// CSS compatibility processing: postcss => postCSs-loader postCSs-preset -env
// Help postcss find the configuration in package.json browserslist and load the specified CSS compatibility content through the configuration
{
loader:"postcss-loader".options: {// webpack 5
postcssOptions: {plugins: ["postcss-preset-env"[// Opitons[]}}}Copy the code
The effect
3. Compress CSS
Install the dependency required by NPM install optimize- CSS -assets-webpack-plugin -d
// Plugins in webpack.config.js are configured as follows
plugins: [new HtmlWebpackPlugin({
template:"./src/index.html"
}),
new MiniCssExtractPlugin({
filename:"css/built.css"
}),
new OptimizeCssAssetsPlugin()
]
Copy the code
The effect
4. Check the js syntax
Use NPM to install eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import -d to install the required dependencies
// Rules for modules in the webpack.config.js configuration configure the following options
module: {rules: [// Syntax check :eslint-loader eslint
// Note: only check your own source code, third-party libraries are not checked
{
test:/\.js$/,
exclude:/node_modules/,
loader:"eslint-loader".options: {// Automatically fixes esLint errors
fix:true}}}]Copy the code
Configure eslintConfig in package.json
5. Js compatibility processing
Run NPM install babel-loader @babel/ core@babel /preset-env-d to install the required dependencies
- 1. Basic JS compatibility processing
@babel/preset-env
Problem: Only basic syntax can be converted, such aspromiseYou cannot convert - 2. All JS compatibility processing
@babel/
Problem: I only want to solve part of the compatibility problem, but it is too bulky to introduce all the compatibility code - 3, need to do compatibility processing to do: load on demand
core-js
module: {rules:[
{
test:/\.js$/,
exclude:/node_module/,
loader:"babel-loader".options: {// Preset: what compatibility processing is instructed to Babel
[
'@babel/preset-env',
{
// Load as needed
useBuiltIns:'usage'.// Specify the core-js version
corejs: {version:3
},
// Specify which version of the browser is compatible with
targets: {chrome:'60'.firefox:'60'.ie:'9'.safari:'10'.edge:'17'}}]}}Copy the code
6. The compression of HTML
NPM install html-webpack-plugin -d
plugins:[
new HtmlWebpackPlugin({
template:'./src/index.html'.minify: {// Remove whitespace
collapseBooleanAttributes:true.// Remove comments
removeComments:true}})]Copy the code
7. The production environment is configured
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const { resolve } = require('path');
const commonCssLoader = [
MiniCssExtractPlugin.loader,
'css-loader',
{
// Browserslist needs to be defined in package.json
loader:'postcss-loader'.options: {postcssOptions: {plugins:[
[
'postcss-preset-env'[// Options[]}}}]// Define the nodeJS environment variable: Determines which environment to use browserslist
process.env.NODE_ENV = 'production';
module.exports = {
entry:"./src/js/index.js".output: {filename:"js/builts.js".path:resolve(__dirname,'build')},module: {rules:[
{
test:/\.css$/,
use:[...commonCssLoader]
},
{
test:/\.less$/,
use:[...commonCssLoader,'less-loader']},// Normally, a file can only be processed by one loader when a file is processed by multiple Loaders
// Specify the order in which the loader executes; Run esLint before Babel
{
test:/\.js$/,
exclude:/node_modules/.// Priority execution
enforce:"pre".loader:"eslint-loader".options: {fix:true}}, {test:/\.js$/,
exclude:/node_modules/,
loader:'babel-loader'.options: {presets:[
[
'@babel/preset-env',
{
useBuiltIns:'usage'.corejs: {versions:3
},
targets: {chrome:'60'.firefox:'50'}}]]}}, {test:/\.(jpg|png|gif)/,
loader:'url-loader'.options: {limit:8 * 1024.name:"[hash:10].[ext]".outputPath:'imas'.esModule:false
},
type:'javascript/auto'
},
{
test:/\.html$/,
loader:'html-loader'}, {exclude:/\.(js|css|less|html|jpg|png|gif)/,
loader:'file-loader'.options: {outputPath:'media'}}},plugins: [new MiniCssExtractPlugin({
filename:'css/built.css'
}),
new OptimizeCssAssetsPlugin(),
new HtmlWebpackPlugin({
template:"./src/index/html".minify: {collapseWhitespace:true.removeComments:true}})].mode:"production"
}
Copy the code
Webpack optimizes configuration
1.HMR (Optimize packing speed)
HMR: Hot Module replacement or hot module replacement
What it does: When a module sends changes, it repackages only that module, not all modules, greatly increasing build speed
-
1. Style files: you can use the HMR function because style-loader is implemented internally
-
2. Js file: HMR function cannot be used by default, js code needs to be modified. Add code to support HMR functionality
Note: the HMR function can only handle non-entry JS files.
if(module.hot){
// Once module.hot is true, HMR is enabled --> HMR is enabled
module.hot.accept('./print.js'.function(){
// The print.js method listens for changes in the print.js file, and when changes occur, other modules are not repackaged and built
// The following callback functions are executedprint(); })}Copy the code
- 3. HTML files: HMR cannot be used by default. It also causes problems: HTML files cannot be hot updated
Solution: Modify the entry entry to import the HTML file
module.exports = {
entry: ['./src/js/index.js'.'./src/index.html'].output: {... }}Copy the code
2. Soure-map (Source code mapping technique)
// Configure the devtool option in webpack.config.js
module.exports = {
entry: ['./src/js/index.js'].output: {... },module:{
...
},
plugins:[
...
]
},
mode:"development".devtool:'hidden-source-map'
Copy the code
Source-map: a technique that provides source-to-build code mapping (mapping to trace source code errors if errors occur after a build)
- 1.
sourec-map
(external) : Error code exact information and source code error location - 2,
inline-source-map
(Inline) : Only one inline is generatedsource-map
Error code exact information and source code error location - 3,
hidden-source-map
(External) : Error code error cause, but there is no error location, can not trace the source code error, only to the error location of the built code - 4,
eval-source-map
(inline) : each file generates the correspondingsource-map
, all ineval
, error code exact information and source code error location - 5,
nosources-source-map
(external) : Error code exact information, but no source code information - 6,
cheap-source-map
(external) : Error code exact information, but no source code information, only down to the line - 7,
cheap-module-source-map
(external) : Error code exact information, but no source code information,module
willloader
thesource-map
join
Development environment: Fast, debug friendly, speed (eval>inline> Cheap >..)
Production environment: Should source code be hidden? Is the mode more friendly?
Inlining can make code larger, so inlining is not used in production. Nosource-source-map is completely hidden, and hidden-source-map only hides the source code, prompting error messages when the code is built
3. Cache (performance optimization of live code)
Babel cache, cacheDirectory: true for faster secondary packaging, file resource caching
- 1.
hash
: a unique webpack is generated each time the webpack is builthash
Value,
Problem: js and CSS use the same hash value, repackaging will invalidate all caches, (maybe I only change one file)
- 2,
chunkshash
: Hash value generated by chunk. If the package comes from the same chunk (entry file), the hash value is the same
Problem: JS and CSS still have the same hash value, because CSS is introduced in JS, so it belongs to the same chunk
- 3,
contenthash
: Generates a hash value based on the content of the file. The hash value must be different for different files
Make the live code cache more usable (live code performance optimization)
// Add the filename suffix to output
module.exports = {
entry:"./src/js/index/js".output: {filename:"js/builts.[contenthash:10].js".path:resolve(__dirname,'build')}},Copy the code
The effect
Create the serve.js file to start the server
// Server code
// Start the server
// npm install nodemon -g
// nodemon server.js
// Access server address: http://localhost:3000
const express = require('express');
const app = express();
The exposed build directory is valid for about 1 hour
app.use(express.static('build', {maxAge: 1000 * 3600 }))
app.listen(3000)
Copy the code
4. Tree shaking
Prerequisites: 1. ES6 modularization must be used; 2
What it does: Reduces code volume and makes requests load faster
Configure in package.json
"sideEffects":false // All code is tree shaking
Copy the code
Change “sideEffects” to “sideEfects” in WebPackage 5
Problem: It is possible to bring CSS /@babel/polyfill files directly into the file
“SideEfects “:[“*.css”
5. Lazyding (lazy loading and preloading)
// In the entry file index.js
document.getElementById('btn').onclick = function (){
// Lazy loading: files are loaded only when they are needed
// Preload: Prefetch preloads the JS file before it is used
// Normal loading can be considered parallel loading (multiple files are loaded at the same time)
// Prefetch: Wait until all other resources are loaded and the browser is free
import(/* webpackChunkName:'test',webpackPrefetch:true */'./test')
.then(({ mul }) = > {
console.log(mul(4.5))})}Copy the code
6.PWA (Progressive Web development application — offline accessible)
Install NPM install workbox-webpack-plugin -d
// Configure plugins in webpack.config.js with the following options
plugins: [new WorkboxWebpackPlugin.GenerateSW({
// 1. Help ServiceWorker start quickly
Delete the old ServiceWorker
// Function: Generate a Serviceworker profile
clientsClaim:true.skipWaiting:true})]1. Eslint does not recognize the window.navigator global variable. Json eslintConfig "env":{"browser":true supports browser-side global variables} 2. Sw code must run on the server --> nodejs --> NPM install serve-g Serve-s build starts the server and exposes all resources in the build directory as static resources */
// Register serviceWorker to handle compatibility issues
if('serviceWorker' in navigator){
window.addEventListener('load'.() = > {
navugator.serviceWorker.register('./service-worker.js')
.then(() = > {
console.log('Sw registered successfully');
}).catch(() = > {
console.log('SW registration failed')})})}Copy the code
7. Multithreaded packaging
Install NPM thread-loader -d
// Rules configuration in module webpack.config.js
{
test:/\.js$/,
exclude:/node_modules/,
use:[
/* Multithreaded packaging is required only when the work takes a long time
{
loader:'thread-loader'.options: {// The number of workers generated, by default, is the number of CPU cores
workers:2.// The number of jobs being performed in a worker process
// The default is 20
workerParallelJobs:50.// Additional Node.js parameters
workerNodeArgs: ['--max-old-space-size'.'1024'].// Delete worker processes when idle
// the default is 500ms
// It can be set to infinite to keep the worker alive in watch mode
poolTimeout:2000.// The number of jobs assigned to the worker by the pool
/ / the default 200
// Lowering this number will reduce overall efficiency, but will improve work distribution more evenly
poolParallelJobs:50.// Pool name
// You can change the name to create a pool with the same other options.
name:'my-pool'}}}]Copy the code
Externals (exclude some packages from packaging)
For example: the jquery
const { resolve } = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry:"./src/js/index.js".output: {filename:"built.js".path:resolve(__dirname,"build")},plugins: [new HTMLWebpackPlugin({
template:"./src/index.html"})].mode:"production".// Reject some package parameters packaging
externals: {// Refuse to package jQuery
jquery:"jQuery"}}Copy the code
DLL (separate package of code)
Use the DllReferencePlugin in Webpack
NPM install add-asset-html-webpack-plugin -d
// Plugins in webpack.config.js are configured as follows
const { resolve } = require('path');
const webpack = require('webpack');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
module.exports = {
// entry:....
plugins: [// Tell WebPack which libraries are not included in the package, and change their names when used
new webpack.DllReferencePlugin({
manifest:resolve(__dirname,"dll/manifest.json")})// Package a file and export it to HTML automatically
new AddAssetHtmlWebpackPlugin({
filepath:resolve(__dirname,"dll/jquery.js"),
// Output directory
outputPath:"auto/"}})]Copy the code
The effect
Webpack configuration details
1. Entry point
-
1. Single entry :string is used to package a chunk file and output a bundle file. In this case, the default name of chunk is main.
Code: entry: ‘. / SRC/index ‘
-
2. Multiple entries: The array type. All entries form only one chunk and only one bundle file is exported.
Code: Entry :[‘./ SRC /add.js’,’./ SRC /count.js’] (HTML hot updates only work in HMR)
-
3. Multiple entries: Object: Several entries form several chunks and output several bundle files. The name of chunk is key
Code: entry: {index: “. / SRC/index. Js “, add: “. / SRC/add. Js “}
-
4. Special usage: All import files end up as one chunk, and only one bundle is exported
Code: entry: {index: [“. / SRC/index. Js “, “. / SRC/count. Js “], the add: “. / SRC/add. Js “}
2. Output (packaged output file directory)
module.exports = {
entry:"./src/index.js".output: {// File name (specified directory + directory)
filname:"js/[name].js".// Output file directory (public directory for future output of all resources)
path:resolve(__dirname,'dist'),
// Introduce a common path prefix for all resources --> "imas/a.jpg --> /imgs/a.jpg"
publicPath:"/".// The name of the non-entry chunk
chunkFilename:'[name]_chunk.js'.// The name of the variable exposed throughout the library
libray:"[name]"./* librayTarget:'window', variable name added to browser librayTarget:'global', variable name added to node librayTarget:'commonjs', To which node */ the variable name is added}}Copy the code
3. Loader configuration in Module
module: {rules: [// Loader configuration
{
// Check some files
test:/\.css$/.// Multiple loaders use use
use:['style-loader'.'css-loader'] {},test:/\.js$/.// Exclude js files under node_modules
exclude:/node_modules/.// Check only js files under SRC
include:resolve(__dirname,'src'),
// Priority execution
enforce:"pre".// The execution is delayed
// enforce:'post'
// Single loader uses loader
loader:"eslint-loader"
},
{
// The following configuration will only generate one
oneOf] : []}}Copy the code
4. Resolve (Resolve module rules)
// Parse the module's rules
resolve: {// Configure the parsing module path alias: advantage short path, disadvantage path is not prompted
alias: {$css:resolve(__dirname,'src/css')},// Omit the suffix of the path
extensions: ['.js'.'.json'.'.jsx'.'.css'].// Tells Webpack which directory to look for
modules:[resolve(__dirname,'.. /.. /node_modules'),'node_modules']}Copy the code
5. DevServer (Development Environment Server)
devServer:{
// Directory to run the code
static: {directory:resolve(__dirname,'build')},/ / comtentBase: resolve (__dirname, 'dist), an error
// Monitor all files in contentBase and reload them if they change
watchContentBase:true.// Monitor files
watchOptions: {// Ignore files and do not participate in monitoring
ignored:/node_modules/
},
// Start gzip compression
compress:true./ / the port number
port:5000./ / domain name
host:"localhost".// Automatically open the browser
open:ture,
// Enable HMR
hot:true.// Do not display startup server logs
clientLogLeval:'none'.// Do not display anything except some basic startup information
quite:true.
// If an error occurs, do not display it in full screen
overlay:false.// Server proxy --> Resolve cross-domain issues in the development environment
proxy: {// Once devServer(5000) receives a request for/API/XXX, it forwards the request to another address
'api': {target:'http://localhost:3000'.// if (/ API/XXX --> / XXX)
pathRewrite: {'^/api':' '}}}}Copy the code
6. Optimization
optimization:{
splitChunks: {chunks:'all'.// The following is the default value
// the minimum size of the chunk to be split is 30kb. If the size is smaller than 30kb, the chunk will not be split
misSize:30 * 1024.// There is no limit to how large a partition can be
maxSize:0.// The chunks to be extracted should be referenced at least once
minChunks:1.// The maximum number of files that can be concurrently loaded on demand is 5
maxAsyncRequests:5.// The maximum number of parallel requests for entry js files is 3
maxInitialRequest:3.// Name concatenation
automaticNameDelimiter:'~'.// You can use naming conventions
name:true.// Split the chunk group
cacheGroups: {// node_modules files are packaged into vendors group chunk --> vendrors~ XXX.js
// Meet the above common rules: if the size exceeds 30KB, be referenced at least once
vendors: {test:/[\\/]node_modules[\\/]/./ / priority
priority:-10
},
default: {// The chunk to be extracted must be referenced at least twice
minChunks:2./ / priority
priority: -20.// If the current module to be packaged is the same module that has already been extracted, it will be reused
reuseExistingChunk:ture
}
}
},
// Package the hash of the current module into a single file runtime
// Error: The contenthash value of file B changes as a result of modifying file A
/ / address:
runtimeChunk: {name:entrypoint= > `runtime=${entrypoint.name}`
},
minimizer: [// Configure the compression scheme for the production environment: JS and CSS
new TerserWebpackPlugin({
// terserOptions:{
// Enable caching
// cache:true,
// Enable multi-threaded packaging
parallel:true./ / start the source - the map
// sourceMap:true}}})]Copy the code