Alternative to html-webpack-plugin ✅ Renders Eta, EJS, Handlebars, Nunjucks, Pug, Twig templates "out of the box" ✅ Resolves source files of scripts, styles, images in HTML ✅ Uses a template as entry point
ISC License
Published by webdiscus about 2 months ago
Supports Node.js version 18+
.
Supports Webpack version 5.81+
.
The plugin option
property is not static anymore:
OLD (up to v3.x)
class MyPlugin extends HtmlBundlerPlugin {
constructor(options = {}) {
super({ ...options });
}
init(compiler) {
// MyPlugin.option. ...; <= was as static property
}
}
NEW (since v4.0)
class MyPlugin extends HtmlBundlerPlugin {
constructor(options = {}) {
super({ ...options });
}
init(compiler) {
// this.option. ...; <= now is non static property
}
}
Using the addProcess()
plugin method is changed:
OLD (up to v3.x)
class MyPlugin extends HtmlBundlerPlugin {
constructor(options = {}) {
super({ ...options });
}
init(compiler) {
// the method was as property of the static `option`
MyPlugin.option.addProcess('postprocess', (content) => {
return content;
});
}
}
NEW (since v4.0)
class MyPlugin extends HtmlBundlerPlugin {
constructor(options = {}) {
super({ ...options });
}
init(compiler) {
// now is the class method
this.addProcess('postprocess', (content) => {
return content;
});
}
}
The watchFiles.files
option has been renamed to watchFiles.includes
.
The files
option is still supported but is deprecated.
It's recommended to replace the files
with includes
in your config.
The watchFiles.ignore
option has been renamed to watchFiles.excludes
.
The ignore
option is still supported but is deprecated.
It's recommended to replace the ignore
with excludes
in your config.
const path = require('path');
const HtmlBundlerPlugin = require('@test/html-bundler-webpack-plugin');
module.exports = [
{
name: 'first',
output: {
path: path.join(__dirname, 'dist/web1/'),
},
plugins: [
new HtmlBundlerPlugin({
entry: {
index: './web1/views/home.html',
},
}),
],
},
{
name: 'second',
output: {
path: path.join(__dirname, 'dist/web2'),
},
plugins: [
new HtmlBundlerPlugin({
entry: {
index: './web2/views/home.html',
},
}),
],
},
];
module.exports = {
name: 'client', // <= this name will displayed in console output
}
Published by webdiscus 2 months ago
v3.13.0
- v3.17.4
?inline
query for styles imported in JavaScript:
import './style-a.css?inline'; // the extracted CSS will be injected into HTML
import './style-b.css'; // the extracted CSS will be saved into separate output file
runtime
option for the handlebars
preprocessor.eta
package to latest version 3.4.0.watchFiles.includes
and watchFiles.excludes
options to allow watch specifically external file,<div style="background-image: url(./image.png);"></div>
?inline
query, #102.integrity
option is enabled but no template defined in entry, #107.>
char, e.g.:
<img src="./arrow.png" alt="right->">
v3.6.0
- v3.12.0
css-loader
option exportType
as css-style-sheet.entry
option is the path.css-loader
>= 7.0.0
{
test: /\.(css)$/,
use: [
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[name]__[local]__[hash:base64:5]',
exportLocalsConvention: 'camelCase',
},
},
},
],
},
CSS:
.red {
color: red;
}
.green {
color: green;
}
Using in JS:
// the styles contains CSS class names: { red: 'main__red__us4Tv', green: 'main__green__bcpRp' }
import styles from './main.css';
const loadStyles = () => import('./component.scss');
loadStyles();
?include
query) compiled CSS directly into style tag to allow keep tag attributes
style(scope='some')=require('./component.scss?include')
will be generate
<style scope="some">
... CSS ...
</style>
class MyPlugin extends HtmlBundlerPlugin {
init(compiler) {
MyPlugin.option.addProcess('postprocess', (content) => {
// TODO: modify the generated HTML content
return content;
});
}
}
module.exports = {
plugins: [
new MyPlugin({
entry: {
index: './src/index.html',
},
}),
],
};
This feature is used in the pug-plugin for pretty formatting generated HTML.require()
function,<a href="#" data-image='{ "alt":"image", "imgSrc": require("./pic1.png"), "bgImgSrc": require("./pic2.png") }'> ... </a>
generated HTML contains resolved output assets filenames:
<a href="#" data-image='{ "alt":"image", "imgSrc": "img/pic1.da3e3cc9.png", "bgImgSrc": "img/pic2.e3cc9da3.png" }'> ... </a>
/* webpackPrefetch: true */
and using the plugin option css.inline=true
, #88HtmlBundlerPlugin
instead of Plugin
.v3.5.1
- v3.5.5
index.ejs?{"title":"Homepage","lang":"en"}
.pug
.responsive-loader
when used query parameters with ,
and &
separators.The entry
option can be as array of entry items:
{
entry: [
{
filename: 'index.html', // output filename in dist/
import: 'src/views/index.html', // template file
data: { title: 'Homepage' }, // page specifically variables
},
{
filename: 'news/sport.html',
import: 'src/views/news/sport/index.html',
data: { title: 'Sport' },
},
],
}
Published by webdiscus 8 months ago
Pug
templating engine.pug
preprocessor based on the @webdiscus/pug-loader source code and has the same options and features.Published by webdiscus 8 months ago
v3.4.7
- v3.4.12
cache.type = 'filesystem'
.cache.type = 'filesystem'
.faviconOptions.path
option.url(date:image...)
in CSS.Published by webdiscus 10 months ago
v3.2.0
- v3.4.6
Twig
templating engine.template function
on the client-side for Eta
templating engine.template function
on the client-side for EJS
templating engine.pathData.filename
is undefined after changes when the js.filename
is a function, #66.link
tag, #64.Published by webdiscus 11 months ago
template function
in JS runtime on the client-side in the browser.import personTmpl from './partials/person.ejs';
// render template function with variables in browser
document.getElementById('person').innerHTML = personTmpl({ name: 'Walter White', age: 50});
The template function works with preprocessors: ejs
, handlebars
, nunjucks
.
Note: The eta
(default preprocessor) doesn't support the template function in JS on the client-side, use the ejs
instead.
*.vue
files.<template>
...
</template>
<script setup>
...
</script>
<!-- CSS will be extracted from the SCSS file into a separate *.css file -->
<style src="./style.scss" lang="scss"></style>
<!-- CSS will be extracted from the style tag into a separate *.css file -->
<style>
h1 {
color: red;
}
</style>
@root
variables in Handlebars partial
helper inside the each
block.Published by webdiscus 11 months ago
plugins
directory to package.Published by webdiscus 12 months ago
Changed arguments
and return
of the postprocess callback option.
OLD < v3.0.0:
postprocess(content: string, info: TemplateInfo, compilation: webpack.Compilation): string | null;
type TemplateInfo = {
filename: string | ((pathData: PathData) => string);
assetFile: string;
sourceFile: string;
outputPath: string;
verbose: boolean | undefined;
};
When return null
then the template processing was skipped.
NEW >= v3.0.0 :
Removed unused/useless properties: filename
, verbose
.
Added properties: name
, resource
.
postprocess(content: string, info: TemplateInfo, compilation: webpack.Compilation): string | undefined;
type TemplateInfo = {
name: string; // the entry name
assetFile: string; // the output asset filename relative to output path
sourceFile: string; // the source filename without a query
resource: string; // the source filename including a query
outputPath: string; // output path of assetFile
};
When return null
or undefined
then the content stay unchanged by postprocess
and will be procedded in next hooks/callbacks.
Added beforePreprocessor hook.
Added beforePreprocessor callback option.
Added preprocessor hook.
Added resolveSource hook.
Added postprocess hook
Optimized postprocess callback option, moved from renderManifest
sync hook to processAssets
async hook.
Added beforeEmit hook.
Added beforeEmit callback option.
Added afterEmit hook.
Added afterEmit callback option.
Added possibility to create own plugin using the hooks: beforePreprocessor
, preprocessor
, resolveSource
, postprocess
, beforeEmit
, afterEmit
.
Added the first plugin (plugin for bundler plugin :-) - FaviconsBundlerPlugin to generate and inject favicon tags for many devices.
For example:
const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');
const { FaviconsBundlerPlugin } = require('html-bundler-webpack-plugin/plugins');
module.exports = {
plugins: [
new HtmlBundlerPlugin({
entry: {
index: './src/views/index.html',
},
}),
// add the plugin to extend the functionality of the HtmlBundlerPlugin
new FaviconsBundlerPlugin({
faviconOptions: { ... }, // favicons configuration options
}),
],
};
If you use the favicons-bundler-plugin
, you need to install the favicons module.
Added possibility to load CSS file dynamically in JavaScript.
For example:
function loadCSS(file) {
const style = document.createElement('link');
style.href = file;
style.rel = 'stylesheet';
document.head.appendChild(style);
}
loadCSS(require('./style.scss?url')); // <= dynamic load the source style file with `url` query
Added js.inline.attributeFilter
option to keep some original script tag attributes when JS is inlined.
For example, keep the id
and text/javascript
attributes by inlined <script id="my-id">...inlined JS code...</script>
:
new HtmlBundlerPlugin({
// ...
js: {
inline: {
attributeFilter: ({ attributes, attribute, value }) => {
if (attribute === 'type' && value === 'text/javascript') return true;
if (attribute === 'id' && attributes?.type === 'text/javascript') return true;
},
},
},
}
exports
field in the package.json.Published by webdiscus 12 months ago
integrity
with the root publicPath
option, like output.publicPath: '/some/path/'
.Published by webdiscus 12 months ago
integrity
with the option output.publicPath: '/'
. Issues: #42, #43Published by webdiscus about 1 year ago
v2.14.1
- v2.15.0
parsedValue
argument as an array of parsed filenames w/o URL query, in the filter()
function of the sources
.parsedValue
is useful to use with the srcset
attribute with many image files.value
argument for srcset
attribute, it is now string
(was as Array<string>
), in the filter()
function of the sources
.srcset
attribute you can use the parsedValue
as an array instead of the value
, the value
contains now an original string.filter()
function of the sources
loader option.serve
mode.isEntry
property from the info
argument of the postprocess
callback.isEntry
property was always true, because template is defined as an entrypoint.Published by webdiscus about 1 year ago
v2.13.0
- v2.14.0
integrityHashes
hook to allow retrieving the integrity values, e.g., into the separate file.beforePreprocessor
callback option, called right before the preprocessor
.Published by webdiscus about 1 year ago
Removed support for the webpack-subresource-integrity
plugin,
because it works not optimized, contains Webpack deprecated code
and the current Release Candidate version not works more without the html-webpack-plugin
what is the BREAKING CHANGE and it will not works with the html-bundler-webpack-plugin
plugin.
Added support for subresource integrity
independent of other plugins.
It was implemented own very compact, optimized and fast code to generate integrity
for link
and script
tags.
CHANGED behavior: the integrity
option defaults is now false
(in v2.11.0 was auto
using webpack-subresource-integrity
plugin).
Extended the integrity
option values with the object to pass additional hashFunctions
option.
Published by webdiscus about 1 year ago
v2.10.0
- v2.11.0
webpack-subresource-integrity
plugin to include the subresource integrity hash.integrity
option to enable/disable the support for webpack-subresource-integrity
plugin.assign
, partial
and block
to extend a template layout with blocks.link
and script
tags" example View in browser | source
Published by webdiscus about 1 year ago
v2.7.0
- v2.9.0
experimental
support the Webpack cache.type
as filesystem
. This is yet an alpha version.cache.type
as memory
.json5
dependency, take only the parser code from this package, remove unused code from it and optimize it for use with the plugin.js.inline.chunk
and js.inline.source
options to inline only js chunks matching regular expressions.hotUpdate
option to false
. This is not breaking change.false
as Webpack automatically injects the hot update code into the compiled js file. Enable this option only if you don't have a referenced source file of a script in a html template..1
, like index.1.js
, when used the same base filename for template and js files. For example, if source files with the same base name src/index.html
and src/index.js
were used, then dist/index.html
and dist/index.1.js
were created, because the entry name used for compilation must be unique. This case is fixed.output.path
, not to CWDasset
module by 2nd npm start
when cache.type
is 'filesystem'
.eta
to the latest v3.1.0
version.Published by webdiscus about 1 year ago
output.path
option is undefined
, set the default path as CWD + /dist
Published by webdiscus about 1 year ago
css.chunkFilename
option for output filename of non-initial chunk files, e.g., a style file imported in JavaScript.hotUpdate
option to enable/disable live reload in serve/watch mode. For some use cases you can disable auto injecting the hot-update.js
into generating html files. For example, when you use a react-app generated with create-react-app
, then this option must be disabled to avoid a react error.Published by webdiscus about 1 year ago