Here’s how to create an HTML for a specific or every entry file using Webpack and HTML Webpack Plugin. A really short explanation.
Table of Contents
Webpack Bundling in a Nutshell
Webpack allows you to bundle your app from one or multiple files. It starts from a file called “entry” and follows your import
or require
calls. It then smartly concatenates your files and even splits them for lazy loading if needed.
Webpack can also accept multiple entries. For each entry, a bundle will be created. When bundling a front end entry point, you sometimes want to generate an HTML file per entry.
If you want to learn webpack from scratch, there’s an old article of mine here that walks you through building a full webpack project.
Real Life Example
Let’s take a look at a real life example from a production setup. You can follow the explanation and run it on your machine locally to better illustrate this use case.
In this setup, we have a UI components library with various components. For each component, we create a test page. This test page is then snapshot-tested using playwright for a visual regression test.
Here’s the repository: https://github.com/Vonage/vivid
The magic happens in the ui-tests folder. If you clone the repository, yarn install and then build the ui-tests (yarn build-ui-tests) webpack will build a ui-tests/tmp
folder as well as a ui-tests/dist
.
In the tmp
folder you’ll find the compiled results of the source code. This is done using a custom webpack plugin that takes the source code and adds it to a test template file.
In dist
folder you’ll find multiple html
and js
files – each for a different component.
If you run yarn ui-tests -s
a webpack-dev-server will run and allow you to browse the test cases corresponding to the files in the dist
folder.
Reasons to use multiple entries with webpack
Generating multiple HTML outputs for multiple entries can be useful for various reasons. You’d might want to generate multiple applications, or to demo upload a static website to github pages
.
In my case, I used it in order to generate dynamic test pages for our visual regression system. I also used the same system to create a development environment for our Design System web components.
This development environment looks like this:
How to generate multiple entries?
The entry
property in the Webpack
configuration can accept an object with named entries. It can look something like this:
{
"entry1": "path/to/entry1",
"entry2": "path/to/entry2"
}
If we have multiple entries, we can even create this object dynamically.
Let’s assume we have multiple components and we can get their names in some way:
const listOfComponents = ['component1', 'component2', 'component3'];
It can be just a manual list of names, as you see in the code above. It can also be something more complex like using nodejs fs
in order to get them from the file system:
const listOfComponents = getComponentsFolders().filter(component => !componentsExcludeList.includes(component));
In any event, we have a list of components – the entry names.
We can now generate a list of named entries. We can do this manually, as we saw above. Or we can accomplish it with code that looks something like this:
const entry = listOfComponents.reduce((entries, componentName) => {
entries[componentName] = path.join(__dirname, `tmp/${componentName}/index.js`);
return entries;
}, {});
entry
looks like this eventually:
Each entry has a name (the property name like vwc-accordion
) and a path to the actual entry file. We will use the entry’s name when generating the HTML files (the number of entries is virually limitless – in our project we have around 30 entries – one for each component).
Inside our webpack.config.js
file we can then use the entry
in order to tell webpack to to create my chunks like this:
Webpack takes the entries and bundles them to their own files according to the output definition: call the bundles according to the entry name and put them all in the dist
folder.
How to generate an HTML output for every entry with HTMLWebpackPlugin?
HTMLWebpackPlugin
accepts two important arguments for the task at hand.
The first is chunks
, which accepts what chunks to add to the HTML file.
The second is filename
– which will define the name of the HTML file.
So all we need to do is generate a list of HTMLWebpackPlugin
instances with the right chunk names. Now that we understand how to generate multiple entries, we can use the same trick in order to generate that list:
In essence, we generate an array of HTMLWebpackPlugin
instances.
Each instance states the chunk
to be used as an entry name – the same we stated in the entry
object for the webpack entry
property. This is how HTMLWebpackPlugin
“knows” to generate the HTML to the specific entrypoint’s bundle.
The filename can be whatever – but makes sense to use the entry name as well (in this case, the componentName
is used for the entry name).
Eventually I wrap it up in the webpack config like this:
And this is all that is behind the magic of multiple HTML files for multiple entries with HTMLWebpackPlugin.
Summary
Generating multiple HTML outputs for multiple entries can be useful for various reasons. It is very easy to generate it using Webpack and HTMLWebpackPlugin.
I used it in order to generate dynamic test pages for our visual regression system. I also used the same system to create a development environment for our Design System web components.
Using the same setup, I’ve created a simple “main page” that allows developers to navigate between the different tests and test them live using a webpack dev server.
I add a main
entry that will connect the other entries by adding another property to the entry
object:
entry.mainPage = (path.join(__dirname, "assets/main.js"));
The main.js
file practically creates a menu that redirects to the other HTML files. In essence, we eventually get a “website” for developers to work with on every component in isolation. Using webpack’s dev server allows us a better development experience. For instance, we get HMR out of the box.
Webpack is a great tool. Very versatile with a huge ecosystem. The HTMLWebpackPlugin was there quite from the start – and I believe it is one of the most popular of webpack’s plugins. Now you know how to use it in order to generate multiple HTML files for multiple entries.
Thanks a lot to Michael Perez and Yuval Bar Levi for the review of this article 🙂