How to use WebPack to build multi-page applications is a problem I have been thinking about and solving. There are lots of examples, lots of ideas on the Internet. At first glance, it’s a little interesting, but at first glance, it’s just that.

Using webPack, a build tool, takes a lot of the thinking out of it.

Our common single-page applications have only one page, and they think about problems and solve them around centralization, so a lot of problems are solved. If you have used vue.js, then you must have used Vue-Router and Vuex. They are typical centralized management modes, but there are many more, not to mention here.

And multi-page application, we can no longer follow the centralized model of the road, because it does not work, which is also a lot of people think that multi-page application is not good, or simply think that Webapck can only do a single page application, and can not do multi-page application.

So, the first point I want to make is: Don’t do multi-page apps the same way you do single-page apps.

The difference between module sharing on a single page and module sharing on multiple pages

  1. Module sharing on a single page is actually the repetition of code blocks in different places on the same page; The sharing of code blocks in multi-page applications requires not only the sharing of the same page, but also the sharing of cross-pages.

    So, the first question to solve is: How do blocks of code from different pages share?

  2. Single page routing management, in fact, according to the trigger conditions of users to achieve different code blocks hidden; However, the route management of multi-page application is different, because it realizes page hopping.

    So, the second question to solve is: how should the navigation of the page be applied?

  3. Single page state management, very popular with developers. Single page is a page, so the management of the data state in the page is also handy, so many pages, it is obviously difficult to rely on its own implementation.

So, the third question to solve is: What about state management for multi-page applications?

Note: This is a silly question, but if you’re building a multi-page APPLICATION with DOM manipulation, you don’t need to do state management. If you’re still using a library like vue.js, you might want to consider switching to multi-page state management, because it’s designed for single-page applications.

Exploration of multi-page applications

Entry:

Webpack can define not only a single file for an entry, but also multiple files.

Familiar with when the page application development for the following code should not be unfamiliar?

Module.exports = {entry: './ SRC /index.js', ···}Copy the code

I first came into contact with a real single-page application project using Angualrjs, using the build tool webapck+gulp, which is the entry file code you see in webpack.config.js.

Later, we came up with array form, which looks like this:

Module. Exports = {entry: ['. / SRC/index. Js', 'bootstrap']...}Copy the code

In this way, you can use Boostrap in any code block by referencing bootstrap with the entry file.

After that, we came to object form with the following code:

Module.exports = {main: './ SRC /index.js' ···}Copy the code

The purpose of this is to give the output file a specific name.

Later, is to do a multi-page application, you need to use the following code:

module.exports = {
  entry: {
    index: './src/index.js',
    aboutUs: './src/aboutus.js',
    contactUs: './src/contactus.js'
  }
}Copy the code

To introduce third-party libraries, we can do something like this:

module.exports = {
  entry: {
    index: ['./src/index.js', 'loadsh'],
    aboutUs: './src/aboutus.js',
    contactUs: ['./src/contactus.js', 'lodash']
  }
}Copy the code

The exploration of webpack3. X

But to share the module code, we need to do something like this:

const CommonsChunkPlugin = require('webpack').optimization.CommonsChunkPlugin
module.exports = {
  entry: {
    index: ['./src/index.js', './src/utils/load.js', 'loadsh'],
    aboutUs: ['./src/aboutus.js', 'loadsh'],
    contactUs: ['./src/contactus.js','./src/utils/load.js', 'lodash']
  },
  plugins: [
        new CommonsChunkPlugin({
            name: "commons",
            filename: "commons.js",
            chunks: ["index", "aboutUs", "contactUs"]
        })
  ]
}Copy the code

This type forms the following project directory structure:

├ ─ ─ the SRC │ ├ ─ ─ common / / public module │ │ ├ ─ ─ a. s │ │ ├ ─ ─ b.j s │ │ ├ ─ ─ SAN Antonio s │ │ ├ ─ surprised ─ jeter s │ ├ ─ ─ uttils/tools / │ │ ├ ─ ─ the load. The js / / Load. Js │ ├─ Heavy Metal Guitar School (a.Exercises, B.Exercises, C.Exercises, D.Exercises) B.js) │ ├─ Bass Exercises – Contactus.js C. s) ├─ Webpack.config.js // CSS ├─ Package.json ├─ yarn.lock

However, the built-in plug-in is more limited. As used above, it only extracts code blocks common to the modules that the Chunks option matches. As shown above, it will only extract loadsh from pindex, aboutUs, contactUs, and not load-.js from index, contactUs.

Of course, we don’t use third-party libraries like this either. We use them like this:

const CommonsChunkPlugin = require('webpack').optimization.CommonsChunkPlugin
module.exports = {
  entry: {
    index: ['./src/index.js', './src/utils/load.js'],
    aboutUs: ['./src/aboutus.js'],
    contactUs: ['./src/contactus.js','./src/utils/load.js'],
    vendors: ['lodash']
  },
  externals: {
    commonjs: "lodash",
    root: "_"
  },
  plugins: [
        new CommonsChunkPlugin({
            name: "commons",
            filename: "commons.js",
            chunks: ["index", "aboutUs", "contactUs"]
        })
  ]
}Copy the code

The ultimate goal for web applications is to generate different HTML pages by matching.

The htML-webpack-plugin is used here.

First, you need to install the HTML-webpack-plugin:

yarn add --dev html-webpack-pluginCopy the code

Then import the plug-in and configure it as follows:

. const HtmlWebapckPlugin = require('html-webpack-plugin'); . plugins: [ ... new HtmlWebapckPlugin({ filename: 'index.html', chunks: ['vendors', 'commons', 'index'] }), new HtmlWebapckPlugin({ filename: 'aboutUs.html', chunks: ['vendors', 'commons', 'aboutUs'] }), new HtmlWebapckPlugin({ filename: 'contactUs.html', chunks: ['commons', 'contactUs'] }) ], ...Copy the code

This gives a basic look for a multi-page framework based on Webpack 3.x.

The exploration of webpack4. X

Using WebPack4.x is completely different. It removes the built-in CommonsChunkPlugin and introduces SplitChunksPlugin, which meets our needs and makes up for the CommonsChunkPlugin.

If you want to fix the problem, it’s easy to extract the index, contacUs module. As listed above, we have three entry points: index, aboutUs, contactUs, SplitChunksPlugin. The plugin takes the code blocks shared by all three entry points, creates a file, and then takes the code blocks shared by each of the two entry points. The code blocks unique to each entry point are then formed into a separate file. If you use a third-party library, like the loadsh we used above, it packages the third-party entry blocks into a separate file.

The configuration file webpack.config.js needs to add the following code:

Optimization: {splitChunks: {chunks: 'all', maxInitialRequests: 20, maxAsyncRequests: 20, minSize: 40}Copy the code

Since SplitChunksPlugin can extract common code between arbitrary entry points, we don’t need to use vendors entry nodes. The code to generate a different page for a match could be modified to look like this:

Const HtmlWebapckPlugin = require('html-webpack-plugin') ··· plugins: [new HtmlWebapckPlugin({filename: 'index.html', chunks: ['index'] }), new HtmlWebapckPlugin({ filename: 'aboutUs.html', chunks: ['aboutUs']}), new HtmlWebapckPlugin({filename: 'contactus.html ', chunks: ['contactUs']}),] ···Copy the code

You can see that the results are getting closer and closer to what we want. There is a problem, however, that the third-party library loadsh was introduced at the entry point index and aboutUs respectively, but the result of the build is to output two third-party library files, which is not what we want. How do we solve this problem, then, because the CHUNKS option of the HTML-webpack-plugin supports multiple entry nodes, we can set up a third party library of entry nodes separately. The configuration code is modified as follows:

. entry: { index: ['./src/index.js', './src/utils/load.js'], aboutUs: ['./src/aboutUs.js'], contactUs: ['./src/contactUs.js','./src/utils/load.js'], vendors: ['loadsh'] }, ... plugins: [ new HtmlWebapckPlugin({ filename: 'index.html', chunks: ['index', 'vendors'] }), new HtmlWebapckPlugin({ filename: 'aboutUs.html', chunks: ['aboutUs', 'vendors'] }), new HtmlWebapckPlugin({ filename: 'contactUs.html', chunks: ['contactUs'] }), ], ...Copy the code

Note: If there are dependencies between different entry points, such as index and vendors above, then the vendors should precede the index because index depends on vendors.

That’s basically the end of this article. Of course, we haven’t covered webPack’s multi-page applications yet, but we’ll cover them in a future article.

The source code

webpack3.x multi-page

webpack4.x multi-page

Article series on building multi-page applications

  • Webpack building multi-page Applications — A Preliminary study
  • Build multi-page applications – single page processing