1. Webpack brief description
1.1 what is webpack
-
Webpack is a static modular packaging tool for modern JavaScript applications;
-
Bundler: WebPack is a packaging tool that helps you package things, so it’s static:
-
The reason for this statement is that we can eventually package the code as the ultimate static resource (deployed to a static server);
-
Modular Module: Webpack supports various modular development by default, ES Module, CommonJS, AMD, etc.
-
Modern: As we said at the front end, it is because of the various problems faced by modern front end development that webPack emerged and developed.
-
Vue-cli-serve Running process
1.2 installation
First we create a directory, initialize NPM, then install Webpack locally, then install WebPack-CLI (this tool is used to run Webpack on the command line) :
mkdir webpack-demo && cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev
Copy the code
-
Webpack installation is currently divided into two parts: WebPack and Webpack-CLI
So what’s the relationship?
-
The webpack command executes the webpack in the. Bin directory of node_modules.
-
Webpack relies on webpack-CLI for execution, and an error will be reported if it is not installed;
-
Webpack-cli code execution, is the real use of WebPack compilation and packaging process;
-
So when we install Webpack, we need to install webpack-CLI as well (the third party scaffolding actually doesn’t use webpack-CLI, but something similar to its own vue-service-CLI)
1.3 Webpack official website documents
-
The official documentation for Webpack is webpack.js.org/
-
The official Chinese document for Webpack is webpack.docschina.org/
-
Click on DOCUMENTATION to go to the DOCUMENTATION page:
-
API: AN API that provides an interface for customizing the compilation process (for example, custom loaders and plugins can refer to the API in this location)
-
BLOG: a BLOG, equivalent to the previous TAB BLOG, containing a number of BLOG posts;
-
CONCEPTS are introduced to some of the core Webpack CONCEPTS such as entry, exit, Loaders, Plugins, etc., but there is no detailed API for parsing them.
-
CONFIGURATION: Webpack detailed CONFIGURATION options, can be queried here, more often as a query manual;
-
There are GUIDES to the use of WebPack to guide you through the webpack process.
-
LOADERS: LOADERS, one of the core of Webpack, can be found here, such as CSS-loader, babel-loader, Lessloader, etc.
-
PLUGINS: PLUGINS, one of the core of Webpack, common PLUGINS can be found here, such as BannerPlugin, CleanWebpackPlugin, MiniCssExtractPlugin, etc.
1.4 Problems existing in traditional development
- What’s wrong with our code? Some syntax browsers are not aware of (especially on older browsers)
- 1. Use ES6 syntax, such as const, arrow functions, etc.
- 2. Using the modular syntax in ES6;
- 3. Use CommonJS modular syntax;
// add.js
export const add = (x,y) = > {
return x + y
}
// index.js
import { add } from './js/add.js'
console.log(add(1.2))
// html<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, Initial-scale =1.0"> <title>Document</title> </head> <body> </body> <script SRC ="./ SRC /index.js"></script> // Uncaught SyntaxError: Cannot use import statement outside a module </html>Copy the code
- Obviously, the above problems make it impossible for us to publish static resources directly, because there are all kinds of compatibility issues when running in the user’s browser.
- We need to package it with a tool that translates it into a syntax that the browser can recognize directly;
1.5 WebPack is packaged by default
- We can package through WebPack and then run the packaged code
- Run webpack directly in the directory to generate a dist folder with a main.js file, which is the one we packed
- We found that it can be packaged normally, but there is a question, how does WebPack determine our entry?
- In fact, when we run Webpack, webPack looks for SRC /index.js in the current directory as an entry;
- So, if the SRC /index.js file does not exist in the current project, an error will be reported;
1.6Webpack configuration file
- You can create a webpack.config.js file in the root directory as the webPack configuration file
const path = require('path')
module.exports = {
entry:'./src/index.js'.// Import file
output: {filename: 'main.js'.// The packaged file name
// Must be an absolute path
path: path.resolve(__dirname, './dist') // dist folder}}Copy the code
2. Core configuration options and webpackcss-loader
file-loader
Webpack packs JS files by default
- But CSS files, IMG files and other direct packaging will be wrong
// document.js
export const documentHtml =() = >{
let div = document.createElement('div')
div.innerHTML = "hello world"
div.className = 'box'
document.body.appendChild(div);
return div;
}
// index.js
import { add } from './js/add.js'
import { documentHtml } from './js/document.js'
import './css/index.css' // Import the CSS file
console.log(add(1.2))
documentHtml();
Copy the code
- Continue compiling commands
npm run build
2.1 the use of CSS – loader
-
What is loader?
-
Loader can be used to convert module source code;
-
We can also think of the CSS file as a module, which we load with import;
-
When loading this module, Webpack does not know how to load it, we have to make the corresponding loader to complete this function;
-
-
Installation of CSS-Loader:
NPM install CSS-loader -d NPM install style-loader -d // The page generates the key loader of the style labelCopy the code
2.2 Loader Configuration Mode
-
Configuration means to specify the configuration information in our webpack.config.js file:
- Module. rules allows us to configure multiple loaders (because we will continue to use other loaders to load other files);
- In this way, loader configuration can be better represented, and later maintenance is convenient. At the same time, you can have a global overview of each loader.
-
Module. rules is configured as follows:
-
The value of the rules attribute is an array: [Rule]
-
A Rule is an object in which multiple properties can be set:
-
Test property: Used to match resources, usually set to a regular expression;
-
[UseEntry] UseEntry is an object that can be used to set other attributes. Loader: There must be a Loader attribute whose value is a string. Options: Optional properties. The value is a string or object. The value is passed into the loader. Query: Currently options are used instead; Pass string (for example: use: [‘style-loader’]) is the abbreviation of loader attribute (for example: use: [{loader: ‘style-loader’}]).
-
Loader attribute: rule-use: short for [{loader}]
const path = require('path')
module.exports = {
entry:'./src/index.js'.output: {filename: 'main.js'.// Must be an absolute path
path: path.resolve(__dirname, './dist')},module: {
rules: [{test: /\.css$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader']}, {},test: /\.scss$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'sass-loader']}, {},test: /\.less$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'less-loader'},]}]}}Copy the code
2.3 Using Other CSS Processors and Loaders
// Sass syntax NPM install sass-loader -d NPM install node-sass -d // less syntax NPM install less-loader -d // The configuration is almost the same as that of 'CSS-loader'Copy the code
3. Load and process other resources
3.1 Using file-loader
- To process images in JPG, PNG, etc., we also need a corresponding
loader
:file-loader
pfile-loader
Is to help us process itimport/require()
Method, and will put it in our output folder; - Of course we can learn how to change its name and its folder later;
import zznhImg from '.. /img/zznh.png' // Import img images
export const documentHtml =() = >{
// Image loading
let img = new Image();
img.src = zznhImg;
document.body.appendChild(img);
return div;
}
Copy the code
- The installation file – loader:
npm install file-loader -D
Copy the code
- Configure rules for handling images:
{
test: /\.(png|jpe? g|gif|svg)$/i,
use:{
loader: 'file-loader'.// Configure the file name and output folder
options: {
name: "[name].[hash:8].[ext]".outputPath: "img"}}}Copy the code
3.2asset module type
The introduction of
- The current version of Webpack in use is WebPack 5
- Before Webpack5, we need to use some loaders to load these resources, such as raw-loader, url-loader, file-loader;
- After Webpackage 5, we can directly use asset Module type to replace the above loaders.
- Asset Module Type replaces all of these loaders by adding 4 new module types:
- Asset/Resource sends a separate file and exports the URL. Previously it was implemented by using file-loader;
- Asset /inline exports the data URI of a resource. Previously it was implemented using url-loader;
- Asset /source Exports the source code for the resource. Previously implemented by using raw-loader;
- Asset automatically selects between exporting a data URI and sending a separate file. Previously, the urL-loader was used and the resource volume limit was configured.
Like loading images
- Use the following methods
{
test: /\.(png|jpe? g|gif|svg)$/i,
type: "asset/resource",}// Modify output to add the assetModuleFilename property
output: {filename: 'main.js'.// Must be an absolute path
path: path.resolve(__dirname, './dist'),
assetModuleFilename:"[name].[hash:8].[ext]".// 'asset Module type'
},
Copy the code
3.3 know the Plugin
- Loader is used to convert specific module types
- Plugins can be used to perform a wider range of tasks, such as packaging optimization, resource management, environment variable injection, and so on
CleanWebpackPlugin
- In the previous demo, we needed to manually remove the dist folder every time we changed some configuration and repackaged it:
- We can help with this by using a plug-in called the CleanWebpackPlugin.
npm install clean-webpack-plugin -D
Copy the code
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module: {},// Plug-in configuration
plugins: [new CleanWebpackPlugin()
]
Copy the code
HtmlWebpackPlugin
- Our HTML file was written in the root directory, and there was no index.html file in the final packaged dist folder.
- During project deployment, it is necessary to have the corresponding entry file index.html;
- So we need to package index.html as well;
- To package HTML, we can use another plug-in: HtmlWebpackPlugin;
npm install html-webpack-plugin -D
Copy the code
const HtmlWebpackPlugin = require('html-webpack-plugin')
module: {},// Plug-in configuration
plugins: [new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title:'webpack learning'})]Copy the code
Generated index.html analysis
-
If we want to add something special to our module
- Such as adding a noscript tag to alert users when their JavaScript is turned off;
- For example, when developing a VUE or React project, we need a root tag that can mount subsequent components
-
We need our own index.html module for this
// Templates in Vue<! DOCTYPEhtml>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<! -- built files will be auto injected -->
</body>
</html>
Copy the code
Custom template data filling
- In the code above, there will be some syntax like <% variable %>, which is how EJS modules populate data
- Configuration is as follows
const HtmlWebpackPlugin = require('html-webpack-plugin')
// Plug-in configuration
plugins: [new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title:'webpack learning'.template:'./public/index.html'})]Copy the code
4. Parse the configuration in Babel and WebPack in depth
4.1 Why is Babel needed?
-
In fact, we rarely touch Babel directly in development, but Babel is now an integral part of front-end development:
- In development, we want to use ES6+ syntax, we want to use TypeScript, we want to develop React projects, they all need Babel;
- So learning Babel is important for understanding how code goes from being written to being online;
- Know the truth, and you will be free to know!
-
So what exactly is Babel? PBabel is a toolchain for converting ECMAScript 2015+ code to backwardly compatible versions of JavaScript in older browsers or for ease of use.
-
Including: syntax conversion, source code conversion, Polyfill to achieve the goal to alleviate the missing features, etc
4-2 Use of plug-ins
- Babel itself can be used as a standalone tool (like PostCSS), not in isolation from build tool configurations such as WebPack
- Babel itself can be used as a standalone tool (like PostCSS), not in isolation from build tool configurations such as WebPack
- @babel/core: the core code of Babel, must be installed
- Babel /cli: allows us to use Babel at the command line
npm install @babel/cli @babel/core
Copy the code
- Use Babel to process our source code
- SRC: is the directory of the source file.
- –out-dir: Specifies the folder dist to output
npx babel src --out-dir dist
Copy the code
- For example, we need to convert arrow functions, var commands, strict functions and so on
We can use preset.
- Install @babel/preset-env:
npm install @babel/preset-env -D
Copy the code
Run the following command: NPX Babel SRC --out-dir dist --presets=@babel/preset-envCopy the code
src/index.js
const info = "hello world"
const add = (info) = > {
console.log(info)
}
add();
dist/index.js
"use strict";
var info = "hello world";
var add = function add(info) {
console.log(info);
};
add();
Copy the code
4-3Underlying principles of Babel
- How does Babel convert one piece of our code (ES6, TypeScript, React) into another (ES5)
- What is the work of converting from one source code (native language) to another source code (target language)
- It’s a compiler, and in fact we can think of Babel as a compiler
- What the Babel compiler does is convert our source code into another piece of source code that the browser can recognize directly;
- Babel also has a compiler workflow
- Parsing
- Transformation phase
- Code Generation
babel-loader
- In real development, we would normally configure Babel to be used in build tools, such as WebPack
- We can set a rule to use our Babel when loading js files
{
test:/\.js$/,
use:{
loader:'babel-loader',}}Copy the code
babel-preset
- If we install the plugins one by one and need to manually manage a large number of Babel plugins, we can just supply webPack with a preset, and WebPack will load the preset list of plugins and pass it to Babel
- For example, there are three common presets
- env
- react
- TypeScript
/ / install preset - env
npm install @babel/preset-env
Copy the code
4.4 Configuration file of Babel
- As before, we can put Babel configuration information in a separate file. Babel gives us two types of configuration file authoring:
- Json (or.js,.cjs,.mjs) files;
- Json (or.js,.cjs,.mjs) files;
- .babelrc.json: used a lot of configuration methods in the early days, but it is more troublesome to configure Monorepos project;
- Babel.config. json (babel7) : works directly with Monorepos project subpackages
{
test:/\.js$/,
use:{
loader:'babel-loader'.options: {presets:[
["@babel/preset-env"]]// plugins:[
// "@babel/plugin-transform-block-scoping",
// "@babel/plugin-transform-arrow-functions"
// ]}}}Copy the code
Configure the Babel. Config. Js
// babel.config.js
module.exports = {
presets: [["@babel/preset-env"]]}// webpack.config.jsPackage the default configuration of Babel into babel.config.js.// NPM run build can package es6 code into ES5 code
Copy the code
5. DevServer and HMR
5.1 Why Do I Set up a Local Server?
- The code we’ve developed so far needs to have two operations in order to run
- Operation 1: NPM run build, compile related code;
- Operation 2: Open the index. HTML code through the Live Server or directly through the browser to view the effect.
- This process is very frequent and can affect our development efficiency, we want to be able to automatically compile and display files when they change
- Webpack provides several options for automatic compilation:
- Webpack watch mode:
- Webpack dev – server;
- webpack-dev-middlewar
5.2 Webpack watch
- Webpack gives us the Watch mode
- In this mode,
webpack
Depending on all the files in the diagram, if one of them is updated, the code will be recompiled - We do not need to run the NPM run build directive manually
- In this mode,
- How do I start the Watch? One of two ways
- Method 1: Add watch: true in the exported configuration.
- Mode 2: Start
webpack
Command, add the –watch identifier
- Here we choose option two, which is in
Package. The json scripts
Add a watch script to:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"."build": "webpack"."watch": "webpack --watch",},Copy the code
NPM run watch // Modify the code to automatically compile the code and refresh the browser.Copy the code
5.3 webpack – dev – server
- The above method can listen for file changes, but it does not automatically refresh the browser:
- Of course, currently we can use live-server in VSCode to do this;
- However, we hope in not applicable
live-server
In the case of, can havelive reloading
(real-time reload) functionality;
- Webpack – dev – server installation
npm install --save-dev webpack-dev-server
Copy the code
- Add a new scripts script
"serve": "webpack serve"
Copy the code
To start the browser, enter HTTP://localhost:8080/ Default port 8080Run NPM run serve// Modify the code to automatically compile the code, the browser can automatically refresh.
Copy the code
5.4 webpack – dev – middleware
- By default,
webpack-dev-server
Has helped us to do everything- Such as through
express
Start a service, such as HMR (Hot module replacement) - If we want to have more freedom, we can use it
webpack-dev-middleware
;
- Such as through
- What is the
webpack-dev-middleware
?webpack-dev-middleware
Webpack is a wrapper that sends webPack processed files to aserver
;webpack-dev-server
It is used internally, however it can also be used as a separatepackage
To allow for more customization as required;
Webpack dev – the use of middleware
Install Express and Webpack-dev-Middleware:
npm install --save-dev express webpack-dev-middleware
Copy the code
Next we need to make some adjustments to the Webpack configuration file to make sure the middleware functionality is enabled correctly:
webpack.config.js
const { options } = require('less')
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode:"development".devtool:"source-map".entry:'./src/index.js'.output: {filename: 'main.js'.// Must be an absolute path
path: path.resolve(__dirname, './dist'),
publicPath: '/'
AssetModuleFilename :"[name].[hash:8].[ext]",// 'assetModule Type' mode
},
devServer: {hot:true
},
module: {rules:[
{
test:/\.js$/,
use:{
loader:'babel-loader'}}},// Plug-in configuration
plugins: [new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title:'webpack learning'}})]Copy the code
PublicPath will also be used in server scripts to ensure file resources are properly accessed at http://localhost:8080, which we will set up later. The next step is to set up our custom Express ‘service:
project
webpack-demo
|- package.json
|- webpack.config.js
+ |- server.js
|- /dist
|- /src
|- index.js
|- /node_modules
Copy the code
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);
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath
}));
// Serve the files on port 8080.
app.listen(8080.function () {
console.log('Webpack Hot Update');
});
Copy the code
Now, add an NPM script to make it easier to run the service:
package.json
{
"name": "webpack"."version": "1.0.0"."description": ""."main": "index.js"."scripts": {
"test": "echo \"Error: no test specified\" && exit 1"."build": "webpack"."watch": "webpack --watch"."serve": "webpack serve"."start": "webpack-dev-server --open"."server": "node server.js"
},
"author": ""."license": "ISC"."devDependencies": {
"@babel/cli": "^ 7.14.3"."@babel/core": "^ 7.14.3"."@babel/preset-env": "^ 7.14.4"."clean-webpack-plugin": "^ 4.0.0 - alpha."."css-loader": "^ 5.2.6." "."express": "^ 4.17.1"."file-loader": "^ 6.2.0"."html-webpack-plugin": "^ 5.3.1"."less": "^ 4.4.1"."less-loader": "^ 9.0.0"."node-sass": "^ 6.0.0"."sass-loader": "^ 12.0.0"."style-loader": "^ 2.0.0." "."webpack": "^ 5.37.1"."webpack-cli": "^ 4.7.0"."webpack-dev-middleware": "^ 5.0.0"."webpack-dev-server": "^ 3.11.2"}}Copy the code
Now, run the NPM run server on your terminal and you’ll get something like this:
Example app listening on port 8080!
<i> [webpack-dev-middleware] waituntil bundle finished: /sockjs-node/info? Emitted by t=1623594425941 Asset main.js 1.4 KiB [emitted] (name: Main) 1 Related asset Asset index.html 234 bytes [emitted]./ SRC /index.js 1.21 KiB [built] [code generated] webpack 5.38.1 compiled successfullyin 1191 ms
Copy the code
Now, open your browser, jump to http://localhost:8080, and you should see your WebPack application running!
5.5 Introduction to Module Hot Replacement (HMR)
What is HMR?
-
HMR stands for Hot Module Replacement, which translates as Hot Module Replacement.
-
Module hot replacement refers to the replacement, addition, and deletion of modules during the running of the application without the need to refresh the entire page.
-
HMR improves the speed of development in the following ways:
-
Do not reload the entire page, which preserves the state of some applications;
-
Update only what needs to be changed to save development time; P modified CSS, JS source code, will be immediately updated in the browser, equivalent to directly modify the style in the browser devTools;
-
How to use HMR?
-
By default, webpack-dev-Servers already support HMR, we just need to turn it on;
-
Without HMR enabled, when we modify the source code, the entire page is automatically refreshed, using live reloading;
-
Start HMR, modify the configuration of Webpack;
devServer:{
hot:true
},
Copy the code
Framework of HMR
- There is a question: do we often need to write manually when developing other projects
module.hot.accpet
What about the API?- For example, when developing Vue and React projects, we modify components and want to perform hot updates. What should we do in this case?
- In fact, the community already has mature solutions for these:
- For example, in vUE development, we use VUe-Loader, which supports HMR of VUE components and provides out-of-the-box experience.
- The react Hot Loader is used to refresh the react Hot Loader. The react Hot Loader is used to refresh the react Hot Loader.
The React of HMR
- Previously, React was aided by
React Hot Loader
To achieve the HMR, has been changed to usereact-refresh
To implement the - The installation implements HMR-related dependencies
npm install -D @pmmmwh/react-refresh-webpack-plugin react-refresh
Copy the code
- Modify the
webpack.config.js
andbabel.config.js
File:
//webpack.config.js
const ReactRefresgWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin')
// Plug-in configuration
plugins: [new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title:'webpack learning'
}),
new ReactRefresgWebpackPlugin()
]
//babel.config.js
module.exports = {
presets: [["@babel/preset-env"]],plugins:[
['react-refresh/babel']]}Copy the code
The Vue HMR
- Vue loading we need to use vue-loader, and vue-loader loading components will help us with HMR processing by default
- Install the dependencies needed to load vUE
npm install vue-loader vue-template-compiler -D
Copy the code
- Modify the
webpack.config.js
const { options } = require('less')
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const loader = require('sass-loader')
module.exports = {
mode:"development".devtool:"source-map".entry:'./src/index.js'.output: {filename: 'main.js'.// Must be an absolute path
path: path.resolve(__dirname, './dist'),
publicPath: '/'
AssetModuleFilename :"[name].[hash:8].[ext]",// 'assetModule Type' mode
},
devServer: {hot:true
},
module: {rules:[
{
test:/\.js$/,
use:{
loader:'babel-loader'}}, {test:/\.vue$/,
use:{
loader: 'vue-loader'}}},// Plug-in configuration
plugins: [new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title:'webpack learning'
}),
new VueLoaderPlugin()
]
}
Copy the code