Multiple Pages
π
Even though webpack is often used for bundling single-page applications, it’s possible to use it with multiple separate pages as well. The idea is similar to the way you generated many output files in the Targets chapter. That’s achievable through MiniHtmlWebpackPlugin
and a bit of configuration.
Possible approaches
π
When generating multiple pages with webpack, you have a couple of possibilities:
- Go through the multi-compiler mode and return an array of configurations. The approach would work as long as the pages are separate, and there is a minimal need for sharing code across them.
- Set up a single configuration and extract the commonalities. The way you do this can differ depending on how you chunk it up.
- If you follow the idea of Progressive Web Applicationsβ (PWA), you can end up with either an app shell or a page shell and load portions of the application as it’s used.
In practice, you have more dimensions. For example, you have to generate i18n variants for pages. These ideas grow on top of the basic approaches. Here we’ll set up single configuration based on which to experiment further.
Generating multiple pages
π
To generate multiple pages with webpack, we can leverage mini-html-webpack-plugin. html-webpack-plugin would work well for the purpose as well and using it would give you access to the plugins written for it. For the demonstration, using the former is enough.
A page should receive title, url, and chunks for deciding which scripts to include to the page. The idea can be modeled as a configuration part as below:
webpack.parts.js
const {
MiniHtmlWebpackPlugin,
} = require("mini-html-webpack-plugin");
exports.page = ({ title, url = "", chunks } = {}) => ({
plugins: [
new MiniHtmlWebpackPlugin({
publicPath: "/",
chunks,
filename: `${url && url + "/"}index.html`,
context: { title },
}),
],
});
To generate multiple pages using the new helper, set up a configuration file:
webpack.multi.js
const { merge } = require("webpack-merge");
const parts = require("./webpack.parts");
module.exports = merge(
{ mode: "production", entry: { app: "./src/multi.js" } },
parts.page({ title: "Demo" }),
parts.page({ title: "Another", url: "another" })
);
Implement a small module to render on the page:
src/multi.js
const element = document.createElement("div");
element.innerHTML = "hello multi";
document.body.appendChild(element);
And add a script to generate the pages:
package.json
{
"scripts": {
"build:multi": "wp --config webpack.multi.js"
}
}
Testing the build
π
After these steps, you have a minimal build with two pages: /
and /another
. To see it in the browser, run npx serve dist
to display the result. You should be able to navigate to both pages any other should not be available.
To control which entries are used on each page, use the chunks
parameter of parts.page
. If you set it to chunks: []
for one of the pages, you should see nothing on the page for example. While experimenting, match the name
given at parts.entry
. The parameter allows capturing chunks generated by Bundle Splitting and doing this would allow you to load a shared vendor
bundle for all pages.
parts.devServer()
helper and a more complex merge
operation based on the target type.
Progressive web applications
π
If you push the idea further by combining it with code splitting and smart routing, you’ll end up with the idea of Progressive Web Applications (PWA). webpack-pwaβ example illustrates how to implement the approach using webpack either through an app shell or a page shell.
App shell is loaded initially, and it manages the whole application, including its routing. Page shells are more granular, and more are loaded as the application is used. The total size of the application is larger in this case. Conversely, you can load initial content faster.
Using Service Workersβ improves offline experience and especially Workboxβ and its associated workbox-webpack-pluginβ can be useful for setting up the approach with minimal effort.
Conclusion
π
Webpack allows you to manage multiple page setups. The PWA approach allows the application to be loaded as it’s used and webpack allows implementing it.
To recap:
- Webpack can be used to generate separate pages either through its multi-compiler mode or by including all the page configuration into one.
- The multi-compiler configuration can run in parallel using external solutions, but it’s harder to apply techniques such as bundle splitting against it.
- A multi-page setup can lead to a Progressive Web Application. In this case, you use various webpack techniques to come up with an application that is fast to load and that fetches functionality as required. Both two flavors of this technique have their own merits.
You’ll learn to implement Server-Side Rendering in the next chapter.