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;