Implementation steps of building multi page program with Webpack

  • 2021-11-01 23:05:24
  • OfStack

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

Principle

Think of the folder where each page is located as a separate single-page program directory, and configure multiple entry and html-webpack-plugin to realize multi-page packaging.

The following is the directory structure of this project


.
 -  src
 The   Off-  pages
 The      -  about
 The      The    -  index.css
 The      The    -  index.html
 The      The    Off-  index.js
 The      Off-  index
 The        -  index.css
 The        -  index.html
 The        Off-  index.js
 Off-  webpack.config.js

Single Page Packaging Basic Configuration

First, let's look at the webpack basic configuration of the single page program in 1


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 program, change its single-entry and single-HTML templates to multi-entry and multi-HTML templates

Multi-page packaging basic configuration

Modified 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 you write this way, you need to add an entry manually for every additional page, which is troublesome. Therefore, we can define a function that generates an entry according to 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 item, it is no longer appropriate to write the output file name to the dead display, 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',
 },
 ...
}

Configuring multiple html-webpack-plugin

As with the entry, you can write different html templates directly into the plug-in configuration. Here we need to configure different chunks for each plug-in 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 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()],
 ...
};

In this way, a simple multi-page project is configured. We can also add hot updates, code segmentation 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;


Related articles: