Webpack is widely used in single-page packaging, with numerous scaffoldings led by create-React-app. Single-page packaging usually packs business JS and CSS into the same HTML file. There is only one HTML file entry for the whole project, but many businesses require different entries for multiple pages. The Webpack-React-multi-Page architecture allows you to implement a multi-page architecture, ensuring that every page can be hot updated and packaged with a clear file hierarchy during project development.
Making the address
The project architecture
Technology USES
react16
webpack4
Html-webpack-plugin generates HTML files
Mini-css -extract- Plugin CSS separate package
Uglifyjs webpack - plugin js compressed
Optimize the CSS - assets - webpack - plugin CSS compression
es6
babel
node
Opn Opens the browser
Compression Enables Gzip compression
express
git
The directory structuregithub
| - webpack - react - multi - page / / project | | - dist / / compile production directory - index | -- index. CSS | -- index. Js | - about | -- about. CSS | - About. Js | | - images - index. HTML. | - about HTML | - node_modules / / the node package | - SRC/directory/development | - | - index/packaging/index page entry Images / | -- app. Js / / js | -- index. The index business SCSS | -- index. Js/js/index page entry | - about packaging / / the about page entry / | - | - images App. Js / / js | -- index. The about business SCSS | -- index. Js / / js entrance the about page | -- template. | - HTML / / HTML template style. The SCSS / / public SCSS | - WebpackConfig / / use in webpack | -- getEntry. Js / / to get entry | -- getFilepath. Js / / traverse folder | -- htmlconfig. Js / / | - each page HTML injection data Package. The json. | - gitignore | -- webpack. Config. Js / / webpack configuration file | - HTTP: / / www.js / / production start the programCopy the code
wiki
Webpack single-page packaging configuration
webpack.config.js
module.exports = (env, argv) => ({
entry: ".src/index.js",
output: {
path: path.join(__dirname, "dist"),
filename: "bundle.js"}, module: { rules: [ ... ] , }, plugins: [ new HtmlWebpackPlugin({ title:"Home page",
filename:"index.html",
favicon:"",
template: "./src/template.html",]}}));Copy the code
This will pack up a file like the one below in the dist folder
<! DOCTYPE html> <html lang="en"</title> <body> <div id="root"></div>
<script type="text/javascript" src="bundle.js"></script>
</body>
</html>
Copy the code
Webpack multi-page packaging configuration
Webpack entry supports two formats
Packaging a single file
module.exports = {
entry: '.src/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'}};Copy the code
Bundle up a bundle.js under dist
Package out multiple files
module.exports = {
entry: {
index:"./src/index.js",
about:"./src/about.js"
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'}};Copy the code
Above, two files, index.js and abou.js, corresponding to the entry attribute name, are packaged under dist
Mount each JS to the appropriate HTML file
We need to use the html-webpack-plugin webpack plugin to add a new HtmlWebpackPlugin({….) to the plugins every time a page is added })
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = (env, argv) => ({
entry: {
index:"./src/index.js",
about:"./src/about.js"
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'}... // Plugins: [new HtmlWebpackPlugin({filename:"index.html"// Generate index.html template:"./src/template.html"}) // chunks:["index"]
}),
new HtmlWebpackPlugin(
{
filename:"about.html"// Generate index.html template:"./src/template.html"}) // chunks:["about"]]}}))Copy the code
The html-webpack-plugin will generate an HTML file named filename from the template. HTML template and package it into the corresponding folder in output. Note that all packaged files are corresponding to the path directory in Output, including HTML. The chunks here are important to note that it determines which JS should be introduced in the HTML. If not, the default is to introduce all packaged JS, which is not what we want.
The above configuration will eventually package the following file structure under DIST
| - dist. | - index js | -- about. Js | -- index. Within HTML / / mount index, js | -- about. Within HTML / / mount the about, jsCopy the code
Through the above configuration, plus devServer, we can already achieve multi-page configuration development, but this is not smart, because every time you add a page, you have to configure it in Wepback, which will be very tedious, so let’s optimize, let’s just focus on the development of the page, the configuration to Webpack.
Webpack multi-page configuration optimization
Let’s look at the file structure under SRC
|-- src
|-- index
|-- app.js
|-- index.scss
|-- index.js
|-- about
|-- app.js
|-- index.scss
|-- index.js
Copy the code
Each folder below SRC corresponds to the JS business of an HTML page. If we directly find the corresponding entry JS of the folder and merge them to generate the corresponding entry, is there no need to write entry manually? Yes
- getEntry.js
/* eslint-env node */ ** * @project: get entry * @author: leinov * @date: 2018-10-11 */ const fs = require("fs"); /** * @param {String} path * @returns {Object} Return entry {"about/aoubt":"./src/about/about.js". } */ module.exports =function getEnty(path){
let entry = {};
letexistpath = fs.existsSync(path); // Whether a directory existsif(existpath){
letreaddirSync = fs.readdirSync(path); Readdirsync.map ((item)=>{let currentPath = `${path}/${item}`;
letisDirector = fs.statSync(currentPath).isDirectory(); // Check if it is a folderif(isDirector && item ! = ="component"/** * the following output format is {"about/about":".src/aobout/index.js"} * The purpose is to pack js into the corresponding folder */ entry['${item}/${item}`] = `${currentPath}/index.js`; }});returnentry; }};Copy the code
Use getEntry in webpack
const getEntry = require("./webpackConfig/getEntry");
const entry = getEntry();
module.exports = (env, argv) => ({
entry: entry,
})
Copy the code
So we get the entry automatically
HTML – webpack – plugin configuration
Since each page needs to be configured with an HTML, we also use the fs module to get the directory under SRC and iterate through the HTML -webpack-plugin
- getFilepath.js
/* eslint-env node */ ** * @project: /* @author: leinov * @date: 2018-10-11 */ const fs = require("fs"); ** @param {String} path path * @returns {Array} ["about"."index"]
*/
module.exports = function getFilePath(path){
let arr = [];
letexistpath = fs.existsSync(path); // Whether a directory existsif(existpath){
letreaddirSync = fs.readdirSync(path); Readdirsync.map ((item)=>{let currentPath = path + "/" + item;
letisDirector = fs.statSync(currentPath).isDirectory(); // Check if it is a folderif(isDirector){ arr.push(item); }});returnarr; }};Copy the code
- htmlconfig.js
/** * @author:leinov * @date: 2018-10-09 */ module.exports={index:{title:"Home page"// filename:"index.html",
template: "./src/template.html",
chunks:["index/index"],
},
about:{
title: "About page"// filename:"about.html",
template: "./src/template.html",
chunks:["about/about"]}};Copy the code
The final configuration of webpack through the above series of packages is as follows
const HtmlWebpackPlugin = require("html-webpack-plugin");
const getEntry = require("./webpackConfig/getEntry");
const getFilePath = require("./webpackConfig/getFilepath");
const htmlconfig =require("./webpackConfig/htmlconfig");
const entry = getEntry("./src"); const htmlarr=[]; // Inject the HTML template getFilePath("./src").map(pathname => {
htmlarr.push(new HtmlWebpackPlugin(htmlconfig[pathname]));
});
module.exports = (env, argv) => ({
entry: entry
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'}... DevServer: {port: 3100, open:true,
},
plugins: [
...htmlarr
]
})
Copy the code
This completes a complete multi-page architecture configuration, refer to the project code for the complete code