I been struggling with this for a week, I been reading another Stackoverflow questions and the SVGR/WEBPACK documentation but I'm unable to solve this.
I wanted to upgrade an old react single-spa application but it had a lot of conflicting dependencies so I simply went and created a new one using the Single Spa Playground web application, everything works great but I can't get my SVG'S as React Components with SVGR/WEBPACK.
The error:
webpack.config.js
const webpackMerge = require("webpack-merge").merge;
const singleSpaDefaults = require("webpack-config-single-spa-react-ts");
module.exports = (webpackConfigEnv, argv) => {
const defaultConfig = singleSpaDefaults({
orgName: "testorg",
projectName: "testproj",
webpackConfigEnv,
argv,
});
return webpackMerge(defaultConfig, {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.svg$/,
use: ["@svgr/webpack"],
},
],
},
});
};
How I'm importing the svg
import TestImg from "../../assets/icons/testimage.svg";
How I'm using the SVG
<TestImg />
declarations.d.ts
I'm not entirely sure how does this works but I also removed this and it's the same.
declare module "*.svg" {
const content: React.FC<React.SVGAttributes<SVGElement>>;
export default content;
}
package.json
{
"name": "@testorg/testproj",
"scripts": {
"start": "webpack serve",
"start:standalone": "webpack serve --env standalone",
"build": "concurrently npm:build:*",
"build:webpack": "webpack --mode=production",
"analyze": "webpack --mode=production --env analyze",
"lint": "eslint src --ext js,ts,tsx",
"format": "prettier --write .",
"check-format": "prettier --check .",
"test": "cross-env BABEL_ENV=test jest",
"watch-tests": "cross-env BABEL_ENV=test jest --watch",
"prepare": "husky install",
"coverage": "cross-env BABEL_ENV=test jest --coverage",
"build:types": "tsc"
},
"devDependencies": {
"@babel/core": "^7.15.0",
"@babel/eslint-parser": "^7.15.0",
"@babel/plugin-transform-runtime": "^7.15.0",
"@babel/preset-env": "^7.15.0",
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.15.0",
"@babel/runtime": "^7.15.3",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.0.0",
"@types/testing-library__jest-dom": "^5.14.1",
"babel-jest": "^27.0.6",
"concurrently": "^6.2.1",
"cross-env": "^7.0.3",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-config-ts-react-important-stuff": "^3.0.0",
"eslint-plugin-prettier": "^3.4.1",
"husky": "^7.0.2",
"identity-obj-proxy": "^3.0.0",
"jest": "^27.0.6",
"jest-cli": "^27.0.6",
"prettier": "^2.3.2",
"pretty-quick": "^3.1.1",
"sass": "^1.56.2",
"sass-loader": "^13.2.0",
"ts-config-single-spa": "^3.0.0",
"typescript": "^4.3.5",
"webpack": "^5.75.0",
"webpack-cli": "^4.8.0",
"webpack-config-single-spa-react": "^4.0.0",
"webpack-config-single-spa-react-ts": "^4.0.0",
"webpack-config-single-spa-ts": "^4.0.0",
"webpack-dev-server": "^4.0.0",
"webpack-merge": "^5.8.0"
},
"dependencies": {
"@datepicker-react/hooks": "^2.8.4",
"@svgr/webpack": "^6.5.1",
"@types/jest": "^27.0.1",
"@types/react": "^17.0.19",
"@types/react-dom": "^17.0.9",
"@types/systemjs": "^6.1.1",
"@types/webpack-env": "^1.16.2",
"date-fns": "^2.29.3",
"prop-types": "^15.8.1",
"react": "^17.0.2",
"react-datepicker": "^4.8.0",
"react-dom": "^17.0.2",
"react-modal": "^3.16.1",
"react-number-format": "^5.1.2",
"react-toastify": "^6.2.0",
"single-spa": "^5.9.3",
"single-spa-react": "^4.3.1",
"styled-components": "^5.3.6"
},
"types": "dist/testorg-testproj.d.ts"
}
The only way it works
The only way I got it working is uninstalling @svgr/webpack and using my imported svg inside of an img tag, as a source.
<img src={TestImg} alt='' width='200' height='200' />
But is not what I want, I need to be able modify the svg fill by props and that's why I need it as a React Component.
Also, I have a LOT of icons and logos in this project, so manually creating a React Component in my project for each image/icon it's not the solution I'm looking for.
Additional information 1
I put a console log for the TestImg and it shows an url, clearly it's not importing it as a component
If I go to the url this is what it shows:
Additional information 2
import { ReactComponent as TestImg } from "../../assets/icons/testimage.svg"
Doesn't work either, it says:
Can't import the named export 'ReactComponent' (imported as 'TestImg') from default-exporting module (only default export is available)
As at the time of posting, Webpack 5 uses 'Asset Resource', so your config would need to be updated to:
Then you import your SVGs like so:
Your
declarations.d.ts
file would be: