I want to use react-svg-loader to import and use some svg assets I have for my app. You can find my webpack config below. The problem, however, is that I am also using some file loaders for svg files. These are needed because parts of my app are importing icons from font awesome, e.g. <i className="fa fa-lock" aria-hidden="true" />
. So I can get the react-svg-loader working by stop having my file loader look for svg files, but then a lot of the icons on my app won't render. If I don't do this then my webpack will fail to build, saying things like:
ERROR in ./node_modules/font-awesome/scss/font-awesome.scss
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/react-svg-loader/lib/loader.js):
NonErrorEmittedError: (Emitted value instead of an instance of Error) Error in parsing SVG: Non-whitespace before first tag.
So how can I resolve these two conflicts? Thanks.
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const DIST_DIR = path.resolve(__dirname, "dist");
const SRC_DIR = path.resolve(__dirname, "src");
const config = {
entry: [
"babel-polyfill",
`${SRC_DIR}/app/index.js`,
`${SRC_DIR}/app/assets/stylesheets/application.scss`,
`${SRC_DIR}/app/components/index.scss`,
"font-awesome/scss/font-awesome.scss",
"react-datepicker/dist/react-datepicker.css",
"rc-time-picker/assets/index.css",
"react-circular-progressbar/dist/styles.css",
"@trendmicro/react-toggle-switch/dist/react-toggle-switch.css",
],
output: {
path: `${DIST_DIR}/app/`,
filename: "bundle.js",
publicPath: "/app/"
},
module: {
rules: [
{
test: /\.svg$/,
use: [
{
loader: "babel-loader"
},
{
loader: "react-svg-loader",
options: {
jsx: true
}
}
]
},
{
enforce: "pre",
test: /\.js$/,
exclude: /node_modules/,
loader: "eslint-loader",
options: {
failOnWarning: false,
failOnError: true
}
},
{
test: /\.js$/,
include: SRC_DIR,
loader: 'babel-loader',
query: {
presets: ['react', 'stage-2']
}
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: ['file-loader?context=src/images&name=images/[path][name].[ext]', {
loader: 'image-webpack-loader',
query: {
mozjpeg: {
progressive: true,
},
gifsicle: {
interlaced: false,
},
optipng: {
optimizationLevel: 7,
},
pngquant: {
quality: '75-90',
speed: 3,
},
},
}],
exclude: path.resolve(__dirname, "node_modules"),
include: __dirname,
},
{
test: /\.woff2?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
// loader: "url?limit=10000"
use: "url-loader"
},
{
test: /\.(ttf|eot|svg)(\?[\s\S]+)?$/,
use: 'file-loader'
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "application.css"
}),
]
};
module.exports = config;
Once you start your application, Webpack will do its thing and you don't need to worry about your SVGs anymore. You can put your SVG files anywhere in your src/ folder and import them wherever you need them as React components. This method is generally referred to as inline-svg .
There are a few ways to use an SVG in a React app: Use it as a regular image. Import it as a component via bundler magic (SVGR) Include it directly as JSX.
A webpack loader allowing for inline usage of a SVG as a React component, or for composing individual SVGs into larger ones. The latest version has been refactored to allow for receiving an SVG/XML string or an JSON.
When there is already any other loader using default export for svg files, @svgr/webpack will always export the React component via named export. If you prefer named export in any case, you may set the exportType option to named. By default, @svgr/webpack includes a babel-loader with an optimized configuration.
A webpack loader allowing for inline usage of a SVG as a React component, or for composing individual SVGs into larger ones. The latest version has been refactored to allow for receiving an SVG/XML string or an JSON object-tree representing an SVG.
Almost every website and web app use Webpack as a bundler to apply some operations on the assets. An easy way to make the SVG integration is to use a Webpack plugin to automatically inline the SVG files' content to the bundled HTML. Let's use html-webpack-plugin to manage the HTML files as a template with Webpack.
A lightweight alternative solution to svgr is react-svg-loader. For the most part, we do not want all our SVG files to be loaded as a React components. We could combine the above methods depending on the use case. All we have to do is update our webpack configuration.
I had similar issues, while trying to load SVG's with react-svg-loader, but Font Awesome SVG's with file-loader. This was the config that I used to solve that problem:
{
test: /\.svg$/,
exclude: path.resolve(__dirname, 'node_modules', 'font-awesome'),
use: ['babel-loader', 'react-svg-loader'],
},
{
test: /\.svg$/,
include: path.resolve(__dirname, 'node_modules', 'font-awesome'),
use: [{
loader: 'file-loader',
options: {
jsx: true,
},
}],
},
If your webpack config is not in the root, correct the exclude/include paths accordingly!
Note that you have multiple rules for SVG's in your webpack config, play with include/excludes to make them all work for your case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With