Not long ago, I wrote a Webpack multi-page boilerplate(Webpack 4-Boilerplate) from scratch, which is convenient for future work out of the box. We hereby record the key points in the development process.
Note: This article does not cover the basics of WebPack in detail, but if not at all, I recommend checking out the basics I wrote earlier
- Build a simple VUE development environment based on WebPack from scratch
- Build a simple WebPack-based React development environment from scratch
Reasons for multi-page packaging
Let’s start with a soul-searching question: Why multiple pages?
React: NPM run dev NPM run build
However, the reality is that in many scenarios, the single-page application development model does not work. For example, companies often develop activity pages: https://www.demo.com/activity/activity1.html https://www.demo.com/activity/activity2.html https://www.demo.com/activity/activity3.html
The above three pages are completely unrelated active pages, and there is no data shared between the pages. However, each page uses the React framework, and all three pages use a common popbox component. In this scenario, the WebPack multi-page packaging solution is needed:
- Keep the traditional single-page app development model: Use Vue, React and other front-end frameworks (jQuery is also available), support modular packaging, and you can treat each page as a single single-page app
- Standalone deployment: Each page is independent and can be deployed separately, decoupling the complexity of the project, and you can even choose different technology stacks on different pages
Therefore, we can think of multi-page apps as beggars’ version of front-end microservices.
Principle of multi-page packaging
First we agreed: SRC /pages directory, each folder is a separate page. Each page has at least two file configurations:
-
App.js: logical entry to the page
-
Index.html: HTML packaging template for a page
SRC/pages ├ ─ ─ page1 │ ├ ─ ─ app. Js │ ├ ─ ─ index. The HTML │ ├ ─ ─ index. The SCSS └ ─ ─ page2 ├ ─ ─ app. Js ├ ─ ─ index. The HTML └ ─ ─ index. The SCSSCopy the code
As we said earlier, each page can be viewed as a single page application.
How are single-page apps packaged? A single page application is configured by entry to the Webpack
module.exports = {
entry: './src/main.js'.// The project entry file, webpack will start from main.js and load and pack all dependent JS files
output: {
path: path.resolve(__dirname, './dist'), // The package file path of the project
filename: 'build.js' // The packaged file name}};Copy the code
Therefore, multi-page applications only need to configure multiple entries
module.exports = {
entry: {
'page1': './src/pages/page1/app.js'./ / page 1
'page2': './src/pages/page2/app.js'./ / page 2
},
output: {
path: path.resolve(__dirname, './dist'),
filename: 'js/[name]/[name]-bundle.js'.// Filename cannot be written to death. You can only get the bundle name from [name]}}Copy the code
At the same time, multiple HTMLWebPackPlugins need to be configured because the index. HTML templates of multiple pages are different.
Note: HtmlWebpackPlugin must have chunks, otherwise the JS of all pages will be injected into the current HTML
module.exports = {
plugins: [
new HtmlWebpackPlugin(
{
template: './src/pages/page1/index.html'.chunks: ['page1'],}).new HtmlWebpackPlugin(
{
template: './src/pages/page2/index.html'.chunks: ['page2'],}),]}Copy the code
The principle of multi-page packaging is to configure multiple pagesentry
And multipleHtmlWebpackPlugin
Details of multi-page packaging
The code segment
- Package third-party libraries (such as React,Fastclick) that are shared by multiple pages into a separate package
vendor.js
- Package logical code shared by multiple pages and global CSS (such as CSS-reset,icon font ICONS) separately
common.js
andcommon.css
- Separate out the runtime code
manifest.js
- Package each page with its own business code
page1.js
andpage1.css
The first three items are common files introduced by each page, and the fourth item is a separate file for each page.
The implementation is also very simple, configuration optimization can be:
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
// Package common code in the business
common: {
name: "common".chunks: "initial".minSize: 1.priority: 0.minChunks: 2.// Use two references before packing
},
// Package third-party library files
vendor: {
name: "vendor".test: /[\\/]node_modules[\\/]/.chunks: "initial".priority: 10.minChunks: 2.// Use two references before packing}}},runtimeChunk: { name: 'manifest' } // Runtime code}}Copy the code
hash
Finally, we want to pack the file with a hash value so that we can make full use of the browser cache. Webpack has hash, chuckhash, Contenthash: In production environments, we usually use contenthash, whereas development environments do not specify hash.
// dev environment
module.exports = {
output: {
filename: 'js/[name]/[name]-bundle.js'.chunkFilename: 'js/[name]/[name]-bundle.js',}}// ProD production environment
module.exports = {
output: {
filename: 'js/[name]/[name]-bundle.[contenthash:8].js'.chunkFilename: 'js/[name]/[name]-bundle.[contenthash:8].js',}}Copy the code
The mock and proxy
Development environments typically require mock data, as well as proxy apis to the server. We can use devServer with mocker-API third-party library implementation.
const apiMocker = require('mocker-api');
// dev environment
module.exports = {
devServer: {
before(app) { // Local mock data
apiMocker(app, path.resolve(__dirname, '.. /mock/index.js'))},proxy: { // Proxy interface
'/api': {
target: 'https://anata.me'.// the backend callback address
changeOrigin: true.secure: false,},}},}Copy the code
Split the WebPack configuration
For general configuration, split the WebPack configuration file into three parts.
Build ├ ─ ─ webpack. Base. Js / / common part ├ ─ ─ webpack. Dev. Js / / dev └ ─ ─ webpack. Prod. Js / / productionCopy the code
The main differences between dev and PROd configurations:
dev
configurationdevServer
To facilitate local debugging and developmentprod
Package compressed files, extract CSS separately (dev does not extract for CSS hot updates), and generate static resource listsmanifest.json
I’ll cover why a manifest.json is generated and how the packaged code is deployed in the next article.