I am using HTML Bundler Webpack Plugin and following the documentation to keep the directory structure for assets: https://github.com/webdiscus/html-bundler-webpack-plugin?tab=readme-ov-file#how-to-keep-source-directory-structure-for-assets.
I've used this plugin in one other project and was able to keep the directory structure but it's not working this time. I have:
- src
- assets
- imgs
- icons
- weather-icons
The plugin is only outputting:
- dist
- assets
- imgs
- icons
It's as if the weather-icons folder doesn't exist.
This is in my config:
{
test: /\.(png|jpe?g|ico|webp|avif|svg|)$/,
type: "asset/resource",
generator: {
filename: ({ filename }) => {
// Keep directory structure for images in dist folder
const srcPath =
"src/assets/imgs";
const regExp = new RegExp(
`[\\\\/]?(?:${path.normalize(srcPath)}|node_modules)[\\\\/](.+?)$`
);
const assetPath = path.dirname(
regExp.exec(filename)[1].replace("@", "").replace(/\\/g, "/")
);
return `imgs/${assetPath}/[name].[contenthash:8][ext]`;
},
},
},
In a previous project I had the same problem with the bundle not including my assets/imgs subfolders so I included multiple paths in srcPath, like this:
const srcPath =
"src/assets/imgs" ||
"src/assets/imgs/icons" ||
"src/assets/imgs/weather-icons";
This solution fixed the problem in my other project, however, it is not working for me on this project and I'm not sure what I'm doing wrong. I've compared my configs/syntax for the two projects and they're the same.
If it's useful, here is my entire webpack config for this project:
const path = require("path");
const HtmlBundlerPlugin = require("html-bundler-webpack-plugin");
module.exports = {
stats: { children: true },
mode: "development",
output: {
path: path.join(__dirname, "dist/"),
clean: true,
},
resolve: {
alias: {
"@scripts": path.join(__dirname, "src/js"),
"@styles": path.join(__dirname, "src/styles"),
"@images": path.join(__dirname, "src/assets/imgs"),
},
},
devtool: "source-map",
plugins: [
new HtmlBundlerPlugin({
entry: [
{
import: "./src/views/index.html",
filename: "index.html",
data: {
title: "Weather App",
},
},
],
js: {
// output filename for JS
filename: "js/[name].[contenthash:8].js",
},
css: {
// output filename for CSS
filename: "css/[name].[contenthash:8].css",
},
}),
],
module: {
rules: [
{
test: /\.(css|sass|scss)$/,
use: [
{
loader: "css-loader",
options: {
import: false,
},
},
],
},
{
test: /\.(png|jpe?g|ico|webp|avif|svg|)$/,
type: "asset/resource",
generator: {
filename: ({ filename }) => {
const srcPath =
"./src/assets/imgs" ||
"./src/assets/imgs/icons" ||
"./src/assets/imgs/weather-icons";
const regExp = new RegExp(
`[\\\\/]?(?:${path.normalize(srcPath)}|node_modules)[\\\\/](.+?)$`
);
const assetPath = path.dirname(
regExp.exec(filename)[1].replace("@", "").replace(/\\/g, "/")
);
return `imgs/${assetPath}/[name].[contenthash:8][ext]`;
},
},
},
],
},
devServer: {
static: path.resolve(__dirname, "dist"),
watchFiles: {
paths: ["src/**/*.*"],
options: {
usePolling: true,
},
},
},
};
I thought maybe something was wrong with the weather-icons folder itself so I removed it from my repo and re-added it, but that didn't fix the problem. All of the files in the subdirectories of my imgs directory are in .svg format.
I've tried searching for this problem but none of the solutions I've found about keeping directory structure are specific to the HTML Bunder Webpack Plugin.
Am I missing anything to make this work? Thanks.
The problem was in the weather-icons.js
file:
const clearDay = new Image();
clearDay.src =
"/Users/jguneratne/repos/weather-app/src/assets/imgs/weather-icons/clear-day.svg";
This image file used in new Image()
will not be processed via Webpack.
You should use the require()
function:
export const weatherIconsData = {
"clear-day": require("@images/weather-icons/clear-day.svg"),
...
}
where @images
is the Webpack alias to the images directory.