reactjs - svgr/webpack Δεν Λειτουργεί Με Το Webpack 5 Και Το SingleSpa
Παλεύω με αυτό εδώ και μία εβδομάδα, διαβάζω άλλες ερωτήσεις στο Stackoverflow και την τεκμηρίωση του SVGR/WEBPACK αλλά δεν μπορώ να το λύσω.
Ήθελα να αναβαθμίσω μια παλιά εφαρμογή react single-spa αλλά είχε πολλές αντικρουόμενες εξαρτήσεις, οπότε απλώς πήγα και δημιούργησα μια νέα χρησιμοποιώντας την διαδικτυακή εφαρμογή Single Spa Playground, όλα λειτουργούν άψογα αλλά δεν μπορώ να πάρω τα SVG μου ως React Components με SVGR/WEBPACK.
Το σφάλμα:
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"],
},
],
},
});
};
Πώς εισάγω το SVG
import TestImg from "../../assets/icons/testimage.svg";
Πώς χρησιμοποιώ το SVG
<TestImg />
δηλώσεις.d.ts
Δεν είμαι εντελώς σίγουρος πώς λειτουργεί αυτό, αλλά επίσης το αφαίρεσα και είναι το ίδιο.
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"
}
Ο μόνος τρόπος που λειτουργεί
Ο μόνος τρόπος που κατάφερα να το κάνω να λειτουργήσει ήταν να απεγκαταστήσω το @svgr/webpack και να χρησιμοποιήσω το εισαγόμενο svg μου μέσα σε ένα tag img, ως πηγή.
<img src={TestImg} alt='' width='200' height='200' />
Αλλά δεν είναι αυτό που θέλω, χρειάζομαι να μπορώ να τροποποιώ το γεμισμα του svg μέσω props και γι' αυτό χρειάζομαι να είναι ως React Component.
Επίσης, έχω ΠΟΛΛΑ εικονίδια και λογότυπα σε αυτό το έργο, οπότε η χειροκίνητη δημιουργία ενός React Component στο έργο μου για κάθε εικόνα/εικονίδιο δεν είναι η λύση που ψάχνω.
Επιπλέον πληροφορία 1
Έβαλα ένα console log για την TestImg και δείχνει ένα url, προφανώς δεν το εισάγει ως component
Αν πάω στο URL, αυτό είναι που εμφανίζει:
Επιπλέον πληροφορίες 2
import { ReactComponent as TestImg } from "../../assets/icons/testimage.svg"
Ούτε λειτουργεί, λέει:
Δεν είναι δυνατή η εισαγωγή του ονομασμένου εξαγωγής 'ReactComponent' (εισαχθέν ως 'TestImg') από το module που εξάγει μόνο την προεπιλεγμένη τιμή (διαθέσιμη είναι μόνο η προεπιλεγμένη εξαγωγή)
Απάντηση #1
Το παρακάτω λειτούργησε για μένα:
Πρώτον, προσθέστε το πακέτο url-loader στο έργο σας:
npm install url-loader --save-dev
Δεύτερον, ενημερώστε το αρχείο σας webpack.config.js ως εξής:
{
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
use: ['@svgr/webpack', 'url-loader'],
},
Στη συνέχεια, στο πραγματικό component κάντε εισαγωγή έτσι:
import { ReactComponent as TestImg } from "../../assets/icons/testimage.svg"
Αυτό θα το διορθώσει και μετά μπορείτε να το χρησιμοποιήσετε έτσι:
<TestImg />
Απάντηση #2
Όπως και κατά την ώρα δημοσίευσης, το Webpack 5 χρησιμοποιεί το 'Asset Resource', οπότε η ρύθμισή σας θα πρέπει να ενημερωθεί σε:
return webpackMerge(defaultConfig, {
module: {
rules: [{
test: /\.s[ac]ss$/i,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.svg$/,
oneOf: [{
issuer: /\.[jt]sx?$/,
resourceQuery: /react/, // *.svg?react
use: [{
loader: '@svgr/webpack',
options: {
icon: true
}
}]
},
{
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 200
}
}
},
],
},
],
},
});Στη συνέχεια εισάγετε τα SVG σας έτσι:
import GreenLogo from '@/svgs/logo-full.svg?react';Το αρχείο σας declarations.d.ts θα ήταν:
declare module '*.svg?react' {
const content: React.FC < React.SVGAttributes < SVGElement >> ;
export default content;
}

