Problem resolving path to svg
Current behaviour
Webpack is emitting my spritesheet, having been loaded by svg-sprite-loader and then extracted, but it cannot be resolved. This has happened since upgrading, both webpack from 4 to 5, and html-webpack-plugin to the latest version.
An answer to a stackoverflow question suggested that it's related to how it tries to resolve xlink:href="svg/spritesheet.svg#logo" in the html. Specifically <svg><use xlink:href="svg/spritesheet.svg#logo"></svg>
I think it's trying to resolve it from the filesystem before it actually exists
I still don't understand why html-webpack-plugin tries to resolve the path, though. It's probably treating the path as an entry and likely it was a breaking change in their 5.0 which you can work around somehow
The spritesheet is emitted, but I get the error:
Error: Child compilation failed:
Module not found: Error: Can't resolve './svg/spritesheet.svg'Expected behaviour ☀️
For html-webpack-plugin to treat the asset as it did in older versions
Reproduction Example
Repo Will leave the problem on the master branch
webpack.config.js from repo:
const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const SpriteLoaderPlugin = require("svg-sprite-loader/plugin");
module.exports = {
entry: {index: "./src/index.ts"},
mode: "development",
devServer: {
static: {
directory: path.resolve(__dirname, 'dist'),
},
port: 3000,
open: {
app: {
name: 'chrome',
},
},
hot: true,
compress: true,
historyApiFallback: true,
watchFiles: ["src/**/*"]
},
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/,
},
{
test: /\.css$/i,
include: path.resolve(__dirname, "src"),
use: ["style-loader", "css-loader", "postcss-loader"]
},
{
test: /\.(png|jpg|jpeg|gif)$/i,
type: 'asset/resource'
},
{
test: /\.svg$/,
use: [
{
loader: 'svg-sprite-loader',
options: {
extract: true,
spriteFilename: 'svg/spritesheet.svg'
},
},
'svgo-loader',
]
},
{
test: /\.html$/,
use: 'html-loader'
},
],
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/index.html',
chunks: ['index'],
// publicPath: true
}),
new SpriteLoaderPlugin()
]
}Asset in html:
<svg class="mx-auto my-16"><use xlink:href="svg/spritesheet.svg#logo"></svg>
Asset import in index.ts:
import './images/logo.svg';
Environment
Node.js v16.14.0
win32 10.0.19044
npm 8.10.0
npm ls webpack:
[email protected] C:\Users\Nick\Tutorials\Tailwind\Projects\clipboard-website
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ ├─┬ @webpack-cli/[email protected]
│ │ └── [email protected] deduped
│ └── [email protected] deduped
├─┬ [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected] deduped
│ └── [email protected] deduped
└─┬ [email protected]
└─┬ [email protected]
└── [email protected] deduped
npm ls html-webpack-plugin
[email protected] C:\Users\Nick\Tutorials\Tailwind\Projects\clipboard-website
└── [email protected]Juho in that SO question suggested using his plugin as a fix, which I'm grateful for, and it does work, but I'm more familiar with yours, and I thought this might be of interest? For the time being I'll probably use his or lazy load the svgs in image tags as he suggests.
Apologies for the wall of text!
Source: jantimon/html-webpack-plugin