HTML Bundler Webpack Plugin
The `html-bundler-webpack-plugin` is a Webpack plugin designed to streamline the creation of single-page or multi-page websites directly from HTML templates. Unlike `html-webpack-plugin` which primarily injects bundled assets, this plugin treats HTML files as entry points, resolving all linked assets (scripts, styles, images, fonts) within the HTML and CSS itself. It handles asset processing and ensures correct output URLs after Webpack's build. Key differentiators include built-in support for numerous template engines like Eta, EJS, Handlebars, Nunjucks, Pug, Tempura, TwigJS, LiquidJS, and Markdown out-of-the-box. It also simplifies asset resolution in CSS without requiring `resolve-url-loader`. The plugin is currently in a very active development state, with version 4.23.0 being the latest stable release, and frequent updates addressing features, fixes, and Webpack compatibility.
Common errors
-
Resolving of source files in the template file failed. File: src/pages/insects-gallery.ejs Error: The 'source' tag starting at XXXX position is missing the closing '>' char.
cause Despite the error message, the HTML syntax for tags like `<source>` is often correct; the plugin's parser might be misinterpreting complex or malformed HTML within templates.fixCarefully inspect the specified HTML template file at the given position. While the error mentions a missing `>`, it can also indicate other parsing issues. Ensure all tags are properly nested and self-closing tags are correctly formatted. Sometimes, simplifying complex HTML structures or ensuring valid HTML5 can resolve this. -
Error: HtmlBundlerPlugin is not a constructor
cause This error typically occurs when attempting to `require` the plugin in a CommonJS context while the package might be primarily ESM, or when incorrectly importing a named export as a default export.fixEnsure you are using `import { HtmlBundlerPlugin } from 'html-bundler-webpack-plugin';` in an ESM-enabled Webpack configuration file (e.g., `webpack.config.mjs` or `webpack.config.js` with `type: module` in `package.json`). If you must use CommonJS, ensure your environment correctly transpiles ESM or the package provides a CJS entry point. -
Plugin could not be registered at 'html-webpack-plugin-before-html-processing'. Hook was not found. BREAKING CHANGE: There need to exist a hook at 'this.hooks'.
cause This error points to a plugin compatibility issue, likely when an older version of `html-webpack-plugin` (or a plugin extending it) is used with a newer Webpack version, or vice-versa, due to changes in Webpack's plugin API hooks.fixAlthough this specific error message refers to `html-webpack-plugin`, the underlying cause (incompatible plugin hooks) can apply to any Webpack plugin. Ensure all Webpack-related packages, including `html-bundler-webpack-plugin` and any plugins that extend it, are compatible with your Webpack version. Update to the latest versions if possible. -
Can't resolve 'file.css' in 'template.html'
cause This error indicates that the plugin cannot locate a CSS file referenced within an HTML template or imported into JavaScript, often due to incorrect paths, missing webpack aliases, or issues with asset processing rules.fixVerify the path to 'file.css' is correct relative to the HTML template or resolve `alias` configuration. Check your `module.rules` in `webpack.config.js` to ensure that CSS files are being correctly handled (e.g., `css-loader`, `sass-loader`) and that the output filename configuration for CSS (`css.filename`) is correctly set.
Warnings
- breaking Version 4.0.0 introduced breaking changes, requiring Node.js 18+ and Webpack 5.81+. Custom plugins extending `HtmlBundlerPlugin` also need to adapt to `option` no longer being a static property.
- breaking Webpack versions >= 5.96.0 introduced undocumented breaking changes in `AssetGenerator` and `CodeGenerationResults` classes, which required specific adaptations in `html-bundler-webpack-plugin` v4.2.0. Older plugin versions will fail with Webpack 5.96+.
- breaking In v4.19.1, the default behavior for inlining SVG images changed. Previously, `<img src='icon.svg'>` would replace the `<img>` tag with the `<svg>` content. Now, by default, it inlines SVG as a base64-encoded data URL.
- breaking The `PreloadFilter` type signature changed in v4.17.0, affecting custom filter functions.
- gotcha Using Webpack's `splitChunks` optimization can lead to 'Can't resolve a CSS file in template' errors, as noted in v4.5.3 release logs.
- gotcha When migrating from `html-webpack-plugin`, note that `html-bundler-webpack-plugin` treats HTML templates as entry points and handles asset resolution internally. This means fewer loaders/plugins might be needed compared to `html-webpack-plugin` setups.
Install
-
npm install html-bundler-webpack-plugin -
yarn add html-bundler-webpack-plugin -
pnpm add html-bundler-webpack-plugin
Imports
- HtmlBundlerPlugin
const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');import { HtmlBundlerPlugin } from 'html-bundler-webpack-plugin';
Quickstart
import path from 'path';
import { fileURLToPath } from 'url';
import { HtmlBundlerPlugin } from 'html-bundler-webpack-plugin';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
mode: 'development',
output: {
path: path.join(__dirname, 'dist'),
clean: true,
},
resolve: {
alias: {
'@images': path.join(__dirname, 'src/images'),
'@styles': path.join(__dirname, 'src/styles'),
'@scripts': path.join(__dirname, 'src/scripts'),
},
},
plugins: [
new HtmlBundlerPlugin({
entry: {
index: './src/views/index.html',
about: './src/views/about.html',
},
js: {
filename: 'js/[name].[contenthash:8].js',
},
css: {
filename: 'css/[name].[contenthash:8].css',
},
}),
],
module: {
rules: [
{
test: /\.(png|jpe?g|svg|ico)$/i,
type: 'asset/resource',
generator: {
filename: 'img/[name].[hash:8][ext]',
},
},
{
test: /\.(scss|css)$/,
use: ['css-loader', 'sass-loader'],
},
{
test: /\.ejs$/,
loader: 'html-bundler-webpack-plugin/preprocessor/ejs',
}
],
},
};
// src/views/index.html
// <!DOCTYPE html>
// <html lang="en">
// <head>
// <meta charset="UTF-8">
// <meta name="viewport" content="width=device-width, initial-scale=1.0">
// <title>Home</title>
// <link href="@styles/main.scss" rel="stylesheet">
// </head>
// <body>
// <h1>Welcome to the Homepage</h1>
// <img src="@images/logo.svg" alt="Logo">
// <script src="@scripts/main.js"></script>
// </body>
// </html>
// src/scripts/main.js
// console.log('Hello from main.js!');
// src/styles/main.scss
// body { font-family: sans-serif; .logo { width: 100px; } }