What is Webpack

Webpack is a packaging tool whose purpose is that all static resources can be packaged. One might ask why webpack? Webpack is the cornerstone of modern front-end technology, and conventional development methods such as jquery, HTML, and CSS static web development have fallen behind. This is the age of MVVM, data-driven interfaces. What Webpack does is analyze the structure of your project, find JavaScript modules and other extensions that browsers don’t run directly (Scss, TypeScript, etc.), and package them into a format that browsers can use.

2. Core concepts of WebPack

Entry: Indicates which module WebPack should use as a starting point for building its internal dependency diagram. Once at the entry point, WebPack finds out which modules and libraries are (directly and indirectly) dependent on the entry point.

Output: Tells WebPack where to Output the resulting files it creates and how to name them./dist by default.

3. Loader (module converter) : Convert all types of files into valid modules that WebPack can handle, and then you can take advantage of WebPack’s packaging capabilities to process them.

Plugins: Inject extension logic at specific points in the Webpack build process to change build results or do what you want.

5. Module: Developers break the program down into discrete functional blocks called modules

.

Three, Webpack execution process

After webpack starts, it will recursively parse all modules that entry depends on in the module configured in the entry. After finding a module, it will find the corresponding conversion rule according to the configured Loader. After module transformation, the modules that the current module depends on will be parsed. These modules will be grouped into entry groups. One entry and all modules that depend on each other are just one chunk. Webpack executes plugin logic at appropriate times throughout the process

Four, webpack simple packaging cases

[4.1] Preparation

Create an empty folder for creating the project. As shown below, I create a folder named webpack_demo on drive D, use terminal to enter the folder and use NPM init command to initialize a package.json file

After you type this command, the terminal will ask you a list of information such as project name, project description, author, etc., but if you don’t want to publish the module, just press Enter. (You can also use NPM init -y to generate the package.json file once, so that the terminal doesn’t ask you questions.)

[4.2] Install webPack

Next, type the following command on the command line to install webpack. If you want to do it all at once, install both the global webPack and the local project webpack first, since some modules will need it later.

npm install webpack --global                Install the global webpack command
npm install webpack webpack-cli --save-dev  // Install the local project module

// Install can be shortened to I,
// --global -g
// --save can be shortened to -s
--save-dev can be shortened to -d
Copy the code

[4.3] Create a file

Create two new folders under webpack_demo, SRC and dist. Then add the index.js and hello.js files under SRC and the index.html files under dist. The project structure is as follows:

Export a module in hello.js

 // hello.js 
 module.exports = function() {
    let hello = document.createElement('div');
    hello.innerHTML = "hello xxx!";
    return hello;
  };Copy the code

Introduce the hello.js module in index.js

// index.js
const hello = require('./hello.js');
document.querySelector("#root").appendChild(hello());Copy the code

Import the bundled JS file bundle.js under index.html


        
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Webpack demo</title>
</head>
<body>
    <div id='root'></div>
    <script src="bundle.js"></script>   <! -- This is the packaged JS file, which we'll temporarily call bundle.js-->
</body>
</html>Copy the code

[4.4] to package

Enter the following command on the terminal to package the package

// If webpack is installed globally, output is the packaged file path, bundle.js is the packaged JS file name

webpack src/index.js --output dist/bundle.js  

// --output can be shortened to -o
// The above command is equivalent to packaging the index.js file from the SRC folder to the bundle.js folder from the dist folderCopy the code

The results are as follows:

As you can see, webpack compiles both index.js and hello.js, since the index.js file introduces the hello.js module, now open index.html and see the result

We have successfully used webpack for packaging, but I am tired of typing such a long command in the terminal. Next, we will learn to use Webpack through configuration files.

[4.5] Use WebPack through configuration files

Create a new configuration file, webpack.config.js, in the root directory of the current project, and write the following simple configuration code, which so far involves only the entry configuration (which is equivalent to our index.js, from which we started packaging) and the exit configuration (which is equivalent to the bundle.js we generated).

// webpack.config.js
const path = require('path');
module.exports = {
    entry: path.join(__dirname, "/src/index.js"), // Import file
    output: {
        path: path.join( __dirname, "/dist"), // The place where the packed files are stored
        filename: "bundle.js" // Output the file name after packaging}}// Path. join is used to join path fragments
// __dirname is a global variable in Node.js that points to the directory where the script is currently being executed, namely D:\webpack_demoCopy the code

With this configuration file, we can pack by simply running the webpack command in the terminal, which automatically references the configuration options in the webpack.config.js file

[4.6] Custom script command in package.json file

Node projects typically have a package.json file that describes the current project and has a scripts property that allows you to customize script commands, such as the package command we ran. You can add custom scripts to scripts:

Then you can use NPM run build to run the script command. What’s the benefit? If the command line is short, the benefit is not obvious, but how can the command line be long? So here we can add the command that needs to be executed every time. After scripts is configured, the NPM run key value is equivalent to running value on the terminal

Build local services

The react and Vue frameworks run on a local server. Can we do the same? Next, how to build local services

[5.1] webpack-dev-server configates the local server

Webpack provides an optional local development server, which is built on Node.js and is a separate component that needs to be installed separately as a project dependency before being configured in Webpack:

npm install webpack-dev-server -DCopy the code

[5.2] devServer configuration item

  • ContentBase: This configuration item specifies the root directory of the server resource. If contentBase is not configured, contentBase defaults to the current directory of execution, usually the root directory of the project
  • Port: specifies the port number for starting the server. The default port number is 8080
  • Host: specifies the server listening address of DevServer. The default value is 127.0.0.1
  • Headers: This configuration item can inject HTTP response headers into an HTTP response. Such as:
    headers: {
      'X-foo': '112233'
    }Copy the code

  • HistoryApiFallback: This configuration item property is used to redirect to a specific page when a 404 page is returned. This configuration item is usually applied to a single page application. For example, if the route cannot be accessed, the system automatically switches to the index. HTML file when the attribute value is set to true. Of course, we can also manually match routes through regex
    // Skip to the index.html page
    historyApiFallback: true

    // Use the re to match the route
    historyApiFallback: {
      rewrites: [{from: /^\/user/.to: '/user.html' },
        { from: /^\/home/.to: '/home.html'}}]Copy the code

  • Hot: this refers to the module configuration items replacement in function, DevServer the default behavior is found in the source code is updated by automatically refresh the entire page to achieve real-time preview, but after open hot replacement module function, it is through without refreshing the whole page by using a new module to replace the old module to achieve real-time preview.
  • Proxy: Sometimes when we use Webpack to start the server locally, because the domain name we use is http://localhost:8081, but our server interface is different, we can use this configuration to solve the cross-domain problem
// Assume that the domain name of the server interface is http://news.baidu.com
proxy: {
  '/api': {
    target: 'http://news.baidu.com'.// The domain name of the target interface
    // Secure: true, // This parameter is used for HTTPS
    changeOrigin: true.// Whether to cross domains
    pathRewrite: {
      '^/api' : ' '  // Rewrite the path}}}Copy the code

  • Inline: Set to true to refresh the page automatically when the source file changes
  • Open: This property is used to automatically open web pages using our system default browser when DevServer starts and the first build is complete.
  • Compress: Indicates whether to enable gzip compression. The value is a Boolean. The default value is false
  • Overlay: This property is used to display errors on the browser page when compiling errors occur. The default value for this property is false. If necessary, set this parameter to true

[5.3] Add configuration items to webpack.config.js

// webpack.config.js
const path = require('path');
module.exports = {
  entry: path.join(__dirname, "/src/index.js"), // Import file
  output: {
    path: path.join(__dirname, "/dist"), // The place where the packed files are stored
    filename: "bundle.js" // Output the file name after packaging
  },
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    hot: true.port: '8080'.inline: true.open: true.overlay: true.proxy: {
      '/api': {
        target: ' '.changeOrigin: true.pathRewrite: {
          '^/api': ' '  
        }
      }
    }
  }
}Copy the code

[5.4] Add startup commands in package.json file

  "scripts": {
    "build": "webpack"."dev": "webpack-dev-server --open"
  },Copy the code

We use dev to start the local server, webpack-dev-server is the command to start the server, – -opn is the command to automatically open the browser after starting the server, at this time we can customize the command mode to show the convenience, multiple commands can be integrated to run. If we define a dev command name, we can run both webpack-dev-server and – -opn

Now enter NPM run dev at the terminal to run the server

In this way, we can view the page in http://localhost:8088/ (to exit the server, press CTRL + C and then press Y to confirm to exit the server).

[5.5] Debug and configure Source Maps

The Source Map is used to solve the problem of debugging code, which is necessary for development. It is not easy to find errors in packaged files. Through the following configuration, we will generate a. Map file corresponding to the package file during packaging, making the compiled code more readable and easier to debug.

// webpack.config.js
const path = require('path');
module.exports = {
  entry: path.join(__dirname, "/src/index.js"), // Import file
  output: {
    path: path.join(__dirname, "/dist"), // The place where the packed files are stored
    filename: "bundle.js" // Output the file name after packaging
  },
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    hot: true.port: '8080'.inline: true.open: true.overlay: true,},devtool: 'source-map' // Generates a complete.map file for debugging, but also slows down packaging
}Copy the code

Once configured, we run NPM run build again to pack and see that there is an extra bundle.js.map in the dist folder. If we have a bug in our code, the browser debug tool will tell us where the error occurred, which is what the devtool: ‘source-map’ configuration item does.

Six, Loaders

Loaders is one of the most powerful functions of WebPack. Through different loaders, WebPack has the ability to call external scripts or tools to realize the processing of files of different formats, such as converting SCSS to CSS, converting ES66, ES7 syntax to syntax that can be recognized by the current browser. JSX into JS and other functions. Loaders needs to be installed separately and configured under modules in webPack.com FIG. Js. Loaders configuration includes the following aspects:

  • Test: a regular expression that matches the extension name of the file loaders is handling (required)
  • Loader: Name of the loader (mandatory)
  • Include /exclude: Manually add files (folders) that must be processed or exclude files (folders) that do not need to be processed (optional)
  • Options: Provide additional setting options for loaders (optional)

[6.1] Configure CSS-Loader

If we want to load a CSS file, we need to install style-loader and CSS-loader

npm install style-loader css-loader -DCopy the code

// webpack.config.js
const path = require('path');
module.exports = {
  entry: path.join(__dirname, "/src/index.js"), // Import file
  output: {
    path: path.join(__dirname, "/dist"), // The place where the packed files are stored
    filename: "bundle.js" // Output the file name after packaging
  },
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    hot: true.port: '8080'.inline: true.open: true.overlay: true,},devtool: 'source-map'.// Generates a complete.map file for debugging, but also slows down packaging
  module: {
    rules: [{test: /\.css$/.// Matches files that end in.css
        use: ['style-loader'.'css-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left}}}]Copy the code

Create a new index.css file in the SRC folder and style the body

/* index.css */
body {
    background: gray;
}Copy the code

Import it in index.js under the SRC folder

// index.js
import './index.css' / / import CSS

const hello = require('./hello.js');
document.querySelector("#root").appendChild(hello());Copy the code

Run NPM run dev to start the server and see that the background color of the page turns to gray

[6.2] Configure sASS

npm install sass-loader node-sass -D // Since sass-loader depends on Node-sass, node-sass must be installedCopy the code

// webpack.config.js
const path = require('path');
module.exports = {
  entry: path.join(__dirname, "/src/index.js"), // Import file
  output: {
    path: path.join(__dirname, "/dist"), // The place where the packed files are stored
    filename: "bundle.js" // Output the file name after packaging
  },
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    hot: true.port: '8080'.inline: true.open: true.overlay: true,},devtool: 'source-map'.// Generates a complete.map file for debugging, but also slows down packaging
  module: {
    rules: [{test: /\.css$/.// Matches files that end in.css
        use: ['style-loader'.'css-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left
      },
      {
        test: /\.(scss|sass)$/.// Re matches files ending in. SCSS and. Sass
        use: ['style-loader'.'css-loader'.'sass-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left}}}]Copy the code

7. Plugins

Plugins are used to extend Webpack functionality, and they take effect throughout the build process to perform related tasks. Loaders and Plugins are often confused, but they are completely different things, so to speak, Loaders are used to process source files during the packaging build process (JSX, Scss, Less..). One at a time, the plug-in does not directly manipulate individual files, it directly affects the entire build process.

[7.1] Use plug-ins

To use a plug-in, install it via NPM and add an instance of the plug-in to the plugins in the webpack.config.js configuration file. Let’s start with a simple copyright notice plug-in.

// webpack.config.js
const path = require('path');
const webpack = require('webpack');  // This plugin does not need to be installed. It is webPack-based and requires the introduction of the WebPack module
module.exports = {
  entry: path.join(__dirname, "/src/index.js"), // Import file
  output: {
    path: path.join(__dirname, "/dist"), // The place where the packed files are stored
    filename: "bundle.js" // Output the file name after packaging
  },
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    hot: true.port: '8080'.inline: true.open: true.overlay: true,},devtool: 'source-map'.// Generates a complete.map file for debugging, but also slows down packaging
  module: {
    rules: [{test: /\.css$/.// Matches files that end in.css
        use: ['style-loader'.'css-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left
      },
      {
        test: /\.(scss|sass)$/.// Re matches files ending in. SCSS and. Sass
        use: ['style-loader'.'css-loader'.'sass-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left}},plugins: [
    new webpack.BannerPlugin(All Rights Reserved.)  // new an instance of the plug-in]}Copy the code

After running the NPM run build package, we can see that the bundle.js file under dist shows the following:

[7.2] Automatically generate HTML files (HtmlWebpackPlugin)

So far we have used the original index.html file and imported bundle.js manually. If we import more than one JS file and change the js file name, we will have to manually change the js file name in index.html. So is it possible to automatically generate index.html and reference the packaged JS? The HtmlWebpackPlugin is used to solve this problem

We made some changes to the project structure:

  1. Delete the entire dist folder
  2. Create a new index.html(name customization) file template in the SRC folder (this is optional, because HtmlWebpackPlugin will generate the default HTML file even if you don’t set the template), here we set the module to make our development more flexible) :
<! -- index.html -->

        
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id='root'>
    </div>
  </body>
</html>Copy the code

Install HtmlWebpackPlugin

npm install html-webpack-plugin -DCopy the code

Introduce HtmlWebpackPlugin and configure the template that references our Settings as follows:

// webpack.config.js
const path = require('path');
const webpack = require('webpack');  // This plugin does not need to be installed. It is webPack-based and requires the introduction of the WebPack module
const HtmlWebpackPlugin = require('html-webpack-plugin'); // Introduce the HtmlWebpackPlugin
module.exports = {
  entry: path.join(__dirname, "/src/index.js"), // Import file
  output: {
    path: path.join(__dirname, "/dist"), // The place where the packed files are stored
    filename: "bundle.js" // Output the file name after packaging
  },
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    hot: true.port: '8080'.inline: true.open: true.overlay: true,},devtool: 'source-map'.// Generates a complete.map file for debugging, but also slows down packaging
  module: {
    rules: [{test: /\.css$/.// Matches files that end in.css
        use: ['style-loader'.'css-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left
      },
      {
        test: /\.(scss|sass)$/.// Re matches files ending in. SCSS and. Sass
        use: ['style-loader'.'css-loader'.'sass-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left}},plugins: [
    new webpack.BannerPlugin(All Rights Reserved.),  // new an instance of the plug-in
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "/src/index.html")// New an instance of the plugin and pass in the relevant parameters}})]Copy the code

The dist folder is automatically generated by running NPM run build, which contains three files: index. HTML, bundle.js and bundle.js.map

Why is the dist folder automatically generated? Because we defined the location of the export file as dist folder in the output export configuration item, and the export file is called bundle.js, HtmlWebpackPlugin will automatically reference the bundle.js file in dist/index.html. If you change the export file name in the webpack.config.js file, dist/index.html will also automatically change the file name.

[7.3] Clean the Dist folder (CleanWebpackPlugin)

Webpack generates files and places them in the Dist folder, but WebPack has no way of keeping track of which files are actually used in the project. It is generally recommended to clean up the Dist folder before each build, so only the files needed are generated, which is where the CleanWebpackPlugin comes in.

npm install clean-webpack-plugin -DCopy the code

// webpack.config.js
const path = require('path');
const webpack = require('webpack');  // This plugin does not need to be installed. It is webPack-based and requires the introduction of the WebPack module
const HtmlWebpackPlugin = require('html-webpack-plugin'); // Introduce the HtmlWebpackPlugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // Introduce the CleanWebpackPlugin
module.exports = {
  entry: path.join(__dirname, "/src/index.js"), // Import file
  output: {
    path: path.join(__dirname, "/dist"), // The place where the packed files are stored
    filename: "bundle.js" // Output the file name after packaging
  },
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    hot: true.port: '8080'.inline: true.open: true.overlay: true,},devtool: 'source-map'.// Generates a complete.map file for debugging, but also slows down packaging
  module: {
    rules: [{test: /\.css$/.// Matches files that end in.css
        use: ['style-loader'.'css-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left
      },
      {
        test: /\.(scss|sass)$/.// Re matches files ending in. SCSS and. Sass
        use: ['style-loader'.'css-loader'.'sass-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left}},plugins: [
    new webpack.BannerPlugin(All Rights Reserved.),  // new an instance of the plug-in
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "/src/index.html")// New an instance of the plugin and pass in the relevant parameters
    }),
    new CleanWebpackPlugin(),  // Delete the file corresponding to path in output by default]}Copy the code

Now, every time we run the NPM Run build, we see that WebPack removes the Dist folder and then produces a new one.

【 7.4 】 hot update (HotModuleReplacementPlugin)

HotModuleReplacementPlugin is a very useful plug-ins, can automatically refresh preview effect after we modify the code.

Setting method:

  1. Add hot: true to the devServer configuration item.
  2. Because HotModuleReplacementPlugin is webpack module’s own, so after introducing webpack, can be directly used in the plugins configuration items.
// webpack.config.js
const path = require('path');
const webpack = require('webpack');  // This plugin does not need to be installed. It is webPack-based and requires the introduction of the WebPack module
const HtmlWebpackPlugin = require('html-webpack-plugin'); // Introduce the HtmlWebpackPlugin
const CleanWebpackPlugin = require('clean-webpack-plugin'); // Introduce the CleanWebpackPlugin
module.exports = {
  entry: path.join(__dirname, "/src/index.js"), // Import file
  output: {
    path: path.join(__dirname, "/dist"), // The place where the packed files are stored
    filename: "bundle.js" // Output the file name after packaging
  },
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    hot: true.port: '8080'.inline: true.open: true.overlay: true,},devtool: 'source-map'.// Generates a complete.map file for debugging, but also slows down packaging
  module: {
    rules: [{test: /\.css$/.// Matches files that end in.css
        use: ['style-loader'.'css-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left
      },
      {
        test: /\.(scss|sass)$/.// Re matches files ending in. SCSS and. Sass
        use: ['style-loader'.'css-loader'.'sass-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left}},plugins: [
    new webpack.BannerPlugin(All Rights Reserved.),  // new an instance of the plug-in
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "/src/index.html")// New an instance of the plugin and pass in the relevant parameters
    }),
    new CleanWebpackPlugin(['dist']),  // The name of the folder to be cleaned
    new webpack.HotModuleReplacementPlugin() // Hot update plugin]}Copy the code

After NPM run dev starts the project, we try to modify the contents of hello.js and see that the browser preview will refresh automatically

Viii. Project optimization and expansion

[8.1] Code separation

Our webpack.config.js configuration file, in fact, does not configure many things, if later added more configuration, will not be dazzling, so the best way is to split it, easy to manage:

Js, webpack.dev.js and webpack.prod.js respectively represent the public configuration file, development environment configuration file and production environment (refers to the environment when the project is launched) configuration file.

2, install a merge module plug-in:

npm install webpack-merge -DCopy the code

3. Split the webpack.config.js code into the three new files above, and then delete the webpack.config.js file as follows:

// webpack.common.js
const path = require('path');
const webpack = require('webpack');  // This plugin does not need to be installed. It is webPack-based and requires the introduction of the WebPack module
const HtmlWebpackPlugin = require('html-webpack-plugin'); // Introduce the HtmlWebpackPlugin
module.exports = {
  entry: path.join(__dirname, "/src/index.js"), // Import file
  output: {
    path: path.join(__dirname, "/dist"), // The place where the packed files are stored
    filename: "bundle.js" // Output the file name after packaging
  },
  module: {
    rules: [{test: /\.css$/.// Matches files that end in.css
        use: ['style-loader'.'css-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left
      },
      {
        test: /\.(scss|sass)$/.// Re matches files ending in. SCSS and. Sass
        use: ['style-loader'.'css-loader'.'sass-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left}},plugins: [
    new webpack.BannerPlugin(All Rights Reserved.),  // new an instance of the plug-in
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "/src/index.html")// New an instance of the plugin and pass in the relevant parameters
    }),
    new webpack.HotModuleReplacementPlugin() // Hot update plugin]}Copy the code

// webpack.dev.js
const path = require('path');
const merge = require('webpack-merge');  // Introduce the webpack-merge function module
const common = require('./webpack.common.js'); / / introduce webpack.com mon. Js

module.exports = merge(common, {   // Merge webpack.common.js into the current file
    devServer: {
        contentBase: path.join(__dirname, "dist"),
        hot: true.port: '8080'.inline: true.open: true.overlay: true,}})Copy the code

// webpack.prod.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // Introduce the CleanWebpackPlugin

module.exports = merge(common, { // Merge webpack.common.js into the current file
    devtool: 'source-map'.// Generates a complete.map file for debugging, but also slows down packaging
    plugins: [
        new CleanWebpackPlugin(),  
    ]
})Copy the code

4. Set package.json to scripts

  "scripts": {
    "build": "webpack --config webpack.prod.js"."dev": "webpack-dev-server --open --config webpack.dev.js"
  },Copy the code

We changed the build command to webpack –config webpack.prod.js, which means to point the package configuration to the webpack.prod.js configuration file, whereas before we only need to use a webpack command. Since the webpack command points to the file name webpack.config.js by default, we have changed the file name, so we need to customize pointing to the new file. The same goes for the dev command.

Then we run NPM run build and NPM run dev, and the effect should be the same as before we split the code.

[8.2] Multiple entrances and multiple exits

So far we have one entry file and one exit file. What if I have more than one entry file? Let’s try it:

The entery entry in webpack.common.js is written as a string, an array, and an object. The entery entry in webpack.common.js is written as a string, an array and an object. Since there are multiple entrances, there must be multiple exits for one-to-one correspondence, so the configuration of entry and output is as follows:

    entry: {
        index: path.join(__dirname, "/src/index.js"),
        index2: path.join(__dirname, "/src/index2.js")},output: {
        path: path.join(__dirname, "/dist"), // The place where the packed files are stored
        filename: "[name].js" // Output the file name after packaging
    },Copy the code

// index2.js
function page2() {
    let element = document.createElement('div');
    element.innerHTML = 'I'm the second entry file';
    return element;
}

document.getElementById('root').appendChild(page2());Copy the code

Js file in dist folder. Index2.js is automatically added to index2.js file in index. HTML. NPM run dev is displayed as follows:

[8.3] Separate the CSS

The idea of Webpack is to pack CSS and JS into a single file, but what if we want to separate CSS?

npm install extract-text-webpack-plugin@next -D  // Add @next to install the latest, otherwise it will failCopy the code

After installing the above plug-in, import and use it in the webpack.common.js file:

// webpack.common.js
const path = require('path');
const webpack = require('webpack');  // This plugin does not need to be installed. It is webPack-based and requires the introduction of the WebPack module
const HtmlWebpackPlugin = require('html-webpack-plugin'); // Introduce the HtmlWebpackPlugin
const ExtractTextPlugin = require('extract-text-webpack-plugin') // Introduce split plugins
module.exports = {
    entry: {
        index: path.join(__dirname, "/src/index.js"),
        index2: path.join(__dirname, "/src/index2.js")},output: {
        path: path.join(__dirname, "/dist"), // The place where the packed files are stored
        filename: "[name].js" // Output the file name after packaging
    },
    module: {
        rules: [{test: /\.css$/.// Matches files that end in.css
                use: ExtractTextPlugin.extract({  // Here we need to call the extract method inside the separate plug-in
                    fallback: 'style-loader'.// The CSS processed by CSS-loader is finally processed by style-loader
                    use: ['css-loader']})}, {test: /\.(scss|sass)$/.// Re matches files ending in. SCSS and. Sass
                use: ['style-loader'.'css-loader'.'sass-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left}},plugins: [
        new webpack.BannerPlugin(All Rights Reserved.),  // new an instance of the plug-in
        new HtmlWebpackPlugin({
            template: path.join(__dirname, "/src/index.html")// New an instance of the plugin and pass in the relevant parameters
        }),
        new webpack.HotModuleReplacementPlugin(), // Hot update plugin
        new ExtractTextPlugin('css/index.css') // Separate the CSS to the index.css folder in the /dist folder]}Copy the code

After running NPM run build, you will find an additional CSS file in the dist folder

[8.4] Eliminate redundant CSS

Sometimes we write too much CSS, we may unconsciously repeat some styles, which causes redundant code, and forget to check before going online. In this regard, we should try to optimize it, Webpack has this function.

npm install purifycss-webpack purify-css glob -DCopy the code

After installation, configure in the webpack.prod.js file, introduce purifyCSS-webPack and Glob plug-ins and use them

// webpack.prod.js
const path = require('path');
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // Introduce the CleanWebpackPlugin
const PurifyCssWebpack = require('purifycss-webpack'); // Introduce the PurifyCssWebpack plugin
const glob = require('glob');  // Introduces the glob module, which is used to scan all CSS references in HTML files

module.exports = merge(common, { // Merge webpack.common.js into the current file
    devtool: 'source-map'.// Generates a complete.map file for debugging, but also slows down packaging
    plugins: [
        new CleanWebpackPlugin(),
        new PurifyCssWebpack({
            paths: glob.sync(path.join(__dirname, 'src/*.html')) // Synchronously scan all CSS references in HTML files})]})Copy the code

Let’s try adding some extra code to the index.css file:

/* index.css */
body {
    background: gray;
}

/* Redundant CSS */
.a {
    color: black;
    font-size: 14px;
    background: red;
}

/* Redundant CSS */
.b {
    height: 50px;
    line-height: 50px;
    border: none;
}Copy the code

Then we run the NPM run build and find that there is no extra.a and.b code in the index.css package:

[8.5] Image processing

To use images, we need to install two Loaders

// Url-loader is dependent on file-loader, so it needs to be installed
npm install url-loader file-loader -D Copy the code

Then configure url-loader in webpack.common.js

// webpack.common.js
const path = require('path');
const webpack = require('webpack');  // This plugin does not need to be installed. It is webPack-based and requires the introduction of the WebPack module
const HtmlWebpackPlugin = require('html-webpack-plugin'); // Introduce the HtmlWebpackPlugin
const ExtractTextPlugin = require('extract-text-webpack-plugin') // Introduce split plugins
module.exports = {
    entry: {
        index: path.join(__dirname, "/src/index.js"),
        index2: path.join(__dirname, "/src/index2.js")},output: {
        path: path.join(__dirname, "/dist"), // The place where the packed files are stored
        filename: "[name].js" // Output the file name after packaging
    },
    module: {
        rules: [{test: /\.css$/.// Matches files that end in.css
                use: ExtractTextPlugin.extract({  // Here we need to call the extract method inside the separate plug-in
                    fallback: 'style-loader'.// The CSS processed by CSS-loader is finally processed by style-loader
                    use: ['css-loader']})}, {test: /\.(scss|sass)$/.// Re matches files ending in. SCSS and. Sass
                use: ['style-loader'.'css-loader'.'sass-loader']  // The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left
            },
            {
                test: /\.(png|jpg|svg|gif)$/.// Re matches the image format name
                use: [
                    { loader: 'url-loader'  // use url-loader}]},]},plugins: [
        new webpack.BannerPlugin(All Rights Reserved.),  // new an instance of the plug-in
        new HtmlWebpackPlugin({
            template: path.join(__dirname, "/src/index.html")// New an instance of the plugin and pass in the relevant parameters
        }),
        new webpack.HotModuleReplacementPlugin(), // Hot update plugin
        new ExtractTextPlugin('css/index.css') // Separate the CSS to the index.css folder in the /dist folder]}Copy the code

Let’s change the background of index.css to an image

/* index.css */
body {
    background: url('./images/bg.jpg') no-repeat;
    background-size: 200px 250px;
    color: #fff;
}Copy the code

The following information is displayed after the NPM run dev command is run:

We’ll see that the background image becomes Base64 because WebPack automatically optimizes the image to reduce the number of requests sent, but what if I want to make it a path?

We can change the loader configuration of webpack.common.js to add options:

module: {
    rules: [{test: /\.css$/.// Matches files that end in.css
        use: ExtractTextPlugin.extract({  // Here we need to call the extract method inside the separate plug-in
          fallback: 'style-loader'.// The CSS processed by CSS-loader is finally processed by style-loader
          use: ['css-loader'].publicPath: '.. / '  // Set a public path for the background image})}, {test: /\.(scss|sass)$/.// Re matches files ending in. SCSS and. Sass
        use: ['style-loader'.'css-loader'.'sass-loader'].// The loader that needs to be used must be in this order, because the calls to the Loader are compiled from right to left
      },
      {
        test: /\.(png|jpg|svg|gif)$/.// Re matches the image format name
        use: [
          {
            loader: 'url-loader'./ / use url - loader
            options: {
              limit: 1000.// Only images smaller than 1KB will be converted to base64. The example image is 1.47KB, so it will not be converted
              outputPath: 'images'.// Set the name of the folder to store the image after packaging},}]},]},Copy the code

[8.6] Compress the code

In WebPack 4.x, js is automatically compressed when you pack, and when NPM run dev runs the server, hot updates are slow when you modify the code. This is because webPack automatically packages the code for you after you modify it, which causes slow efficiency in the development environment. So we need to separate the development environment from the production environment. This is where we can easily separate our code. Webpack.dev.js represents the configuration of the development environment, webpack.prod.js represents the configuration of the production environment. In this case, we simply configure the commands for the environment in package.json:

  "scripts": {
    "build": "webpack --config webpack.prod.js --mode production"."dev": "webpack-dev-server --open --config webpack.dev.js --mode development"
  },Copy the code

–mode production means that the package is a production environment and will compress js itself, while –mode development means that the package is a development environment and does not need to compress JS. This also solves a lingering warning problem

NPM run dev = NPM run dev


The article is updated every week. You can search “Front-end highlights” on wechat to read it in the first time, and reply to [Books] to get 200G video materials and 30 PDF books