This is my first time building a web-application, and I’m in my final steps. I’m trying to bundle the whole project with webpack, and everything seems to work, except for my SVG-Icons.
I think the problem is how webpack references the svg’s in the compiled index.html.
The original index.html references the svg’s like this:
<svg role="img">
<use href="images/icons.svg#settings-icon"></use>
</svg>
The compiled index.html references the svg’s like this:
<svg role="img" style="margin-bottom:-3px">
<use href="aaf2f945f2b181c45647.svg#settings-icon"></use>
</svg>
This is my dist/ folder after compiling:
dist/
├── images/
│ └── icons.svg
├── aaf2f945f2b181c45647.svg
├── bundle.js
└── index.html
aaf2f945f2b181c45647.svg contains this:
export default "images/icons.svg";
icons.svg contains all my svg’s as it should.
When I replace all "aaf2f945f2b181c45647.svg" with "images/icons.svg" in the compiled index.html, everything works fine.
The problem is that webpack seems to be trying to navigate to icons.svg via aaf2f945f2b181c45647.svg. Why does it do that? Can I somehow tell it to directly write "images/icons.svg" into the html file?
This is my webpack.config.cjs:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
entry: './frontend/src/scripts/index.ts', // Entry point of your application
output: {
filename: 'bundle.js', // Output bundle file name
path: path.resolve(__dirname, 'frontend/dist'), // Output directory
clean: true,
},
module: {
rules: [
{
test: /.ts$/,
use: 'ts-loader',
exclude: /node_modules/,
},
{
test: /.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /.svg$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
publicPath: 'images/',
},
},
},
{
test: /.html$/,
use: 'html-loader',
},
],
},
resolve: {
extensions: ['.ts', '.js'],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './frontend/public/index.html', // Template HTML file
filename: 'index.html', // Output HTML file name
}),
],
};
This is my complete folder structure:
dist/
├── images/
│ └── icons.svg
├── aaf2f945f2b181c45647.svg
├── bundle.js
└── index.html
public/
├── images/
│ └── icons.svg
└── index.html
src/
├── scripts/
│ └── ...
└── styles/
└── ...
I already tried using url-loader, svg-url-loader and svg-sprite-loader instead. None of them was able to display my svg’s.
2
Answers
Use url-loader with webpack
{ test: /.svg$/, loader: "url-loader?limit=10000&mimetype=image/svg+xml" }
Why not use
html-loader
for handling HTML files to ensure thatuse
tags are processed correctly and also updatefile-loader
settings to handle SVGs correctly within HTML as below: