Movatterモバイル変換


[0]ホーム

URL:


Skip to main content

Migrating from HTML Webpack Plugin

For years, configuringhtml-webpack-plugin for multiple pages was a hassle.Each page required manually defining thechunks option to reference JavaScript files from the entry configuration,leading to a frustrating "chunks hell" configuration.

Also,html-webpack-plugin alone is not enough. Rendering an HTML template containing JS, CSS, SVG, images and other assets requires additional "crutches" as plugins forhtml-webpack-plugin, as well additional plugins and loaders.

Thus, this plugin requires a whole bunch of additional plugins and loaders, many of which have not been supported for a long time, which limits the use of the plugin itself.

To solve this and many other problems,was createdhtml-bundler-webpack-plugin — an "all-in-one" solution that simplifies HTML handlingand automatically manages asset dependencies with ease.

Multiple pages example

my-project/
├── dist/ (generated output)
├── src/
│ ├── scripts/
│ │ ├── main.js
│ ├── pages/
│ │ ├── home/
│ │ │ ├── index.html
│ │ │ ├── style.scss
│ │ │ ├── script.js
│ │ ├── about/
│ │ │ ├── index.html
│ │ │ ├── style.scss
│ │ │ ├── script.js
├── webpack.config.js
└── package.json
  • src/pages/home/index.html
  • src/pages/home/script.js
<!DOCTYPEhtml>
<htmllang="en">
<head>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<h1>Home</h1>
</body>
</html>

Webpack config:

const path=require('path');
constMiniCssExtractPlugin=require('mini-css-extract-plugin');
constHtmlWebpackPlugin=require('html-webpack-plugin');

module.exports={
output:{
filename:'js/[name].[contenthash:8].js'
},
entry:{
main:'./src/scripts/main.js',
home:'./src/pages/home/script.js',
about:'./src/pages/about/script.js',
},
plugins:[
newMiniCssExtractPlugin({
filename:'css/[name].[contenthash:8].css',
}),
newHtmlWebpackPlugin({
template:'./src/pages/home/index.html',
filename:'index.html',// Output dist/index.html
title:'Home',
chunks:['main','home'],// Include scripts in this template
inject:'body',
}),
newHtmlWebpackPlugin({
template:'./src/pages/about/index.html',
filename:'about.html',// Output dist/about.html
title:'About',
chunks:['main','about'],// Include scripts in this template
inject:'body',
}),
],
module:{
rules:[
{
test:/\.s?css$/,
use:[
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader',
],
},
],
},
};

Step by step

First,installhtml-bundler-webpack-plugin.

Step 1: Replace packages

Thehtml-bundler-webpack-plugin replaces the functionality ofhtml-webpack-plugin,mini-css-extract-plugin, and otherplugins and loaders:

- const MiniCssExtractPlugin = require('mini-css-extract-plugin');
- const HtmlWebpackPlugin = require('html-webpack-plugin');
+ const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');

Step 2: Remove loaders

Thehtml-bundler-webpack-plugin extracts CSS automatically.

RemoveMiniCssExtractPlugin.loader from the module rule:

{
test: /\.s?css$/,
use: [
- MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader',
],
},

Or if usedstyle-loader, remove it from the module rule:

{
test: /\.s?css$/,
use: [
- 'style-loader',
'css-loader',
'sass-loader',
],
},
warning

Ensure thatcss-loader is first in theuse: [] array and no other loaders come before it,because the plugin relies on the result ofcss-loader to extract CSS.

Step 3: Replace plugin

Replace allHtmlWebpackPlugin with singleHtmlBundlerPlugin:

  • Place the options object of eachHtmlWebpackPlugin instance intoentry collection ofHtmlBundlerPlugin.
  • Rename thetemplate property toimport.
  • Place template variables, e.g.title, intodata option.
  • Remove needless options, such aschunks,chunksSortMode,excludeChunks,inject, etc.
plugins: [
- new HtmlWebpackPlugin({
- template: './src/pages/home/index.html',
- filename: 'index.html', // Output dist/index.html
- title: 'Home',
- chunks: ['main', 'home'], // Include scripts in this template
- inject: 'body',
- }),
- new HtmlWebpackPlugin({
- template: './src/pages/about/index.html',
- filename: 'about.html', // Output dist/about.html
- title: 'About',
- chunks: ['main', 'about'], // Include scripts in this template
- inject: 'body',
- }),
+ new HtmlBundlerPlugin({
+ entry: [
+ {
+ import: './src/pages/home/index.html',
+ filename: 'index.html', // Output dist/index.html
+ data: { title: 'Home', },
+ },
+ {
+ import: './src/pages/about/index.html',
+ filename: 'about.html', // Output dist/about.html
+ data: { title: 'About', },
+ },
+ ],
+ }),
],

Step 4: Move JS output filename

Move theoutput.filename to thejs.filename plugin option to keep related options at the same place:

module.exports = {
output: {
- filename: 'js/[name].[contenthash:8].js',
},
plugins: [
new HtmlBundlerPlugin({
entry: [ ... ],
+ js: {
+ filename: 'js/[name].[contenthash:8].js',
+ },
}),
],
};

Step 5: Move CSS output filename

Addcss.filename to the plugin options and removeMiniCssExtractPlugin:

module.exports = {
plugins: [
- new MiniCssExtractPlugin({
- filename: 'css/[name].[contenthash:8].css',
- }),
new HtmlBundlerPlugin({
entry: [ ... ],
js: { ... },
+ css: {
+ filename: 'css/[name].[contenthash:8].css',
+ },
}),
],
};

Step 6: Add<script> and<link> tags into HTML

Specify source script and style files in an HTML template using a relative path or a Webpack alias:

<!DOCTYPE html>
<html lang="en">
<head>
+ <link href="./style.scss" rel="stylesheet">
</head>
<body>
...
+ <script src="../../scripts/main.js"></script>
</body>
</html>
tip

UseWebpack alias to avoid relative paths like../../scripts/main.js:

- <script src="../../scripts/main.js"></script>
+ <script src="@scripts/main.js"></script>

Specify aliases in the Webpack config:

module.exports = {
+ resolve: {
+ alias: {
+ '@scripts': path.join(__dirname, 'src/scripts'),
+ },
+ },
};

Remove Webpack entry option, because your scripts and styles are specified directly in HTML:

module.exports = {
- entry: {
- main: './src/scripts/main.js',
- home: './src/pages/home/script.js',
- about: './src/pages/about/script.js',
- },
};

Optional: delete empty JS files containing imported styles only, because source styles specified directly in HTML.

info

The plugin supports imported styles in JS, so you can leave it as is.

Step 7: Check template variables

The template variables defined in thedata option are available in a template w/o any prefix.Just removehtmlWebpackPlugin.options. in the template:

- <title><%= htmlWebpackPlugin.options.title %></title>
+ <title><%= title %></title>
tip

To pass a variable into all templates use the globaldata plugin option.

Final Webpack config

  • NEW: using HtmlBundlerPlugin
  • OLD: using HtmlWebpackPlugin
const path=require('path');
constHtmlBundlerPlugin=require('html-bundler-webpack-plugin');

module.exports={
resolve:{
alias:{
'@scripts': path.join(__dirname,'src/scripts'),
},
},
plugins:[
newHtmlBundlerPlugin({
entry:[
{
import:'./src/pages/home/index.html',
filename:'index.html',// Output dist/index.html
data:{title:'Home',},
},
{
import:'./src/pages/about/index.html',
filename:'about.html',// Output dist/about.html
data:{title:'About',},
},
],
js:{
filename:'js/[name].[contenthash:8].js',
},
css:{
filename:'css/[name].[contenthash:8].css',
},
}),
],
module:{
rules:[
{
test:/\.s?css$/,
use:[
'css-loader',
'sass-loader',
],
},
],
},
};

[8]ページ先頭

©2009-2025 Movatter.jp