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 commandsnpm 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 correspondingloader:file-loader pfile-loaderIs 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 typeThe 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,webpackDepending 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
  • How do I start the Watch? One of two ways
    • Method 1: Add watch: true in the exported configuration.
    • Mode 2: StartwebpackCommand, add the –watch identifier
  • Here we choose option two, which is inPackage. The json scriptsAdd 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 applicablelive-serverIn 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-serverHas helped us to do everything
    • Such as throughexpressStart a service, such as HMR (Hot module replacement)
    • If we want to have more freedom, we can use itwebpack-dev-middleware;
  • What is thewebpack-dev-middleware?
    • webpack-dev-middlewareWebpack is a wrapper that sends webPack processed files to aserver;
    • webpack-dev-serverIt is used internally, however it can also be used as a separatepackageTo 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 projectsmodule.hot.accpetWhat 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 byReact Hot LoaderTo achieve the HMR, has been changed to usereact-refreshTo implement the
  • The installation implements HMR-related dependencies
npm install -D @pmmmwh/react-refresh-webpack-plugin react-refresh
Copy the code
  • Modify thewebpack.config.jsandbabel.config.jsFile:
//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 thewebpack.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

6. Environment separation and code separation

7.DLL_Tree Shaking

8.Tree Shaking and other optimizations

Package analysis and Webpack source code

10. Customize the Loader

11. Custom Plugin

12. Automated build tool gulp

13. Modular package build tool rollup

14. Development pattern builder tool Vite