Implementation steps for building multi-page programs using Webpack

Implementation steps for building multi-page programs using Webpack

It is very common to use webpack to build single-page programs, but in actual development we may also need to develop multi-page programs, so I studied how to use webpack to build multi-page programs.

principle

Treat the folder where each page is located as a separate single-page program directory, and configure multiple entries and html-webpack-plugin to achieve multi-page packaging.

The following is the directory structure of this project

.
├─ src
│ └─ pages
│ ├─ about
│ │ ├─ index.css
│ │ ├─ index.html
│ │ └─ index.js
│ └─ index
│ ├─ index.css
│ ├─ index.html
│ └─ index.js
└─ webpack.config.js

Single page packaging basic configuration

First, let's take a look at the basic configuration of webpack for single-page applications.

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
 entry: './src/index.js',
 plugins: [
  new HtmlWebpackPlugin({
   template: './src/index.html',
   filename: 'index.html',
  }),
 ],
 output: {
  path: path.resolve(__dirname, './dist'),
  filename: 'bundle.js',
 },
};

To change it to a multi-page application, you need to change its single entry and single HTML template to multiple entry and multiple HTML templates.

Basic configuration of multi-page packaging

Renovation entrance

Traditional multi-entry writing can be written in the form of key-value pairs

module.exports = {
 entry: {
  index: './src/pages/index/index.js',
  about: './src/pages/about/index.js',
 },
 ...
}

If written in this way, each additional page needs to manually add an entry, which is troublesome. Therefore, we can define a function to generate an entry based on the directory to simplify our operation.

const glob = require('glob');

function getEntry() {
 const entry = {};
 glob.sync('./src/pages/**/index.js').forEach((file) => {
  const name = file.match(/\/pages\/(.+)\/index.js/)[1];
  entry[name] = file;
 });
 return entry;
}

module.exports = {
 entry: getEntry(),
 ...
}

Transformation output

In the output configuration, it is no longer appropriate to hard-code the output file name, so we need to change the name to match the source file name

module.exports = {
 ...
 output: {
  path: path.resolve(__dirname, './dist'),
  filename: 'js/[name].[contenthash].js',
 },
 ...
}

Configure multiple html-webpack-plugins

Same as the entry, different html templates can be written directly into the plugin configuration. Here we need to configure different chunks for each plugin to prevent js from being injected into the wrong html

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
 ...
 plugins: [
  new HtmlWebpackPlugin({
   template: './src/pages/index/index.html',
   chunks: ['index'],
   filename: 'index.html',
  }),
  new HtmlWebpackPlugin({
   template: './src/pages/about/index.html',
   chunks: ['about'],
   filename: 'about.html',
  }),
 ],
 ...
};

This approach has the same problem as the entry, so we define another function to generate this configuration

const HtmlWebpackPlugin = require('html-webpack-plugin');
const glob = require('glob');

function getHtmlTemplate() {
 return glob
  .sync('./src/pages/**/index.html')
  .map((file) => {
   return { name: file.match(/\/pages\/(.+)\/index.html/)[1], path: file };
  })
  .map(
   (template) =>
    new HtmlWebpackPlugin({
     template: template.path,
     chunks: [template.name.toString()],
     filename: `${template.name}.html`,
    })
  );
}

 
module.exports = {
 ...
 plugins: [...getHtmlTemplate()],
 ...
};

Such a simple multi-page project has been configured. We can also add hot update, code splitting and other functions on this basis. If you are interested, you can try it yourself.

Complete Configuration

Project address: xmy6364/webpack-multipage

// webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const glob = require('glob');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

//Multi-page entry function getEntry() {
 const entry = {};
 glob.sync('./src/pages/**/index.js').forEach((file) => {
  const name = file.match(/\/pages\/(.+)\/index.js/)[1];
  entry[name] = file;
 });
 return entry;
}

//Multi-page template function getHtmlTemplate() {
 return glob
  .sync('./src/pages/**/index.html')
  .map((file) => {
   return { name: file.match(/\/pages\/(.+)\/index.html/)[1], path: file };
  })
  .map(
   (template) =>
    new HtmlWebpackPlugin({
     template: template.path,
     chunks: [template.name.toString()],
     filename: `${template.name}.html`,
    })
  );
}

const config = {
 mode: 'production',
 entry: getEntry(),
 output: {
  path: path.resolve(__dirname, './dist'),
  filename: 'js/[name].[contenthash].js',
 },
 module: {
  rules:
   {
    test: /\.css$/,
    use: ['style-loader', 'css-loader'],
   },
  ],
 },
 plugins: [new CleanWebpackPlugin(), ...getHtmlTemplate()],
 devServer: {
  contentBase: path.join(__dirname, 'dist'),
  compress: true,
  port: 3000,
  hot: true,
  open: true,
 },
};

module.exports = config;

This concludes this article on the implementation steps of using Webpack to build a multi-page program. For more relevant content about building multiple pages with Webpack, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Electron-vue uses webpack to package multiple pages of entry files
  • Implementation of webpack code fragmentation
  • How to debug loader plugin in webpack project
  • 80 lines of code to write a Webpack plugin and publish it to npm
  • 50 lines of code to implement Webpack component usage statistics
  • webpack -v error solution

<<:  How to configure Nginx to support ipv6 under Linux system

>>:  Linux C log output code template sample code

Recommend

How to assign default values ​​to fields when querying MySQL

need When querying a field, you need to give the ...

Introduction to the use and advantages and disadvantages of MySQL triggers

Table of contents Preface 1. Trigger Overview 2. ...

MySQL 5.7.25 installation and configuration method graphic tutorial

There are two types of MySQL installation files, ...

Fabric.js implements DIY postcard function

This article shares the specific code of fabricjs...

Vuex modularization and namespaced example demonstration

1. Purpose: Make the code easier to maintain and ...

Application example tutorial of key in Vue page rendering

introduction During the front-end project develop...

HTML cellpadding and cellspacing attributes explained in pictures

Cell -- the content of the table Cell margin (tabl...

MySQL 8.0.15 compressed version installation graphic tutorial

This article shares the installation method of My...

How to ensure transaction characteristics of MySQL InnoDB?

Preface If someone asks you "What are the ch...

HTML+CSS+jQuery imitates the search hot list tab effect with screenshots

Copy code The code is as follows: <!DOCTYPE ht...

4 principles for clean and beautiful web design

This article will discuss these 4 principles as t...

Detailed explanation of galera-cluster deployment in cluster mode of MySQL

Table of contents 1: Introduction to galera-clust...

JavaScript implements an input box component

This article example shares the specific code for...

Does the % in the newly created MySQL user include localhost?

Normal explanation % means any client can connect...