javascript - Hvordan få SVG React-komponentimporter fra ekstern modul til å fungere med create-react-app?
Kontekst
For å gjøre noen kodebiter gjenbrukbare på tvers av mange React-prosjekter, har jeg følgende prosjektstruktur:
@foo/design: Inneholder designelementer som rå SVG-bilder@foo/ui: Et React-bibliotek basert på Create React App for vanlige komponenter@foo/project: Et endelig CRA-prosjekt som brukerfoo/ui
Biblioteket
Biblioteket foo/ui eksporterer en komponent som importerer et SVG-bilde fra @foo/design:
// MyComponent.ts
import React, { FC } from 'react';
import {
ReactComponent as Logo,
} from '@foo/design/static/img/logo.svg';
export const MyComponent: FC = () => {
return (
<div>
Some stuff.
<Logo />
</div>
);
};
export default null;
Denne komponenten fungerer feilfritt på den relaterte Storybook-instansen av @foo/ui og blir kompilert ved hjelp av tsc på denne måten:
// MyComponent.js
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { ReactComponent as Logo, } from '@foo/design/static/img/logo.svg';
export var Navbar = function () {
return (_jsxs("div", { children: ["Some stuff.", _jsx(Logo, {}, void 0)] }, void 0));
};
export default null;
Her er også den tilhørende tsconfig.json-filen:
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"declaration": true,
"outDir": "./lib",
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx"
},
"include": ["src"],
"exclude": [
"src/samples",
"src/**/*.stories.*",
"src/**/*.test.*",
"src/setupTests.js"
],
}
Prosjektimporten
På @foo/project la jeg til @foo/ui-avhengigheten og installerte også @foo/design-pakken (påkrevd av @foo/ui).
Jeg bruker komponenten min på denne måten:
import { FC } from 'react';
import { MyComponent } from '@foo/ui'
const App: FC = () => {
return (
<MyComponent />
);
}
export default App;
Men dette gir følgende feil:
Failed to compile.
./node_modules/@foo/ui/lib/MyComponent.js
Attempted import error: 'ReactComponent' is not exported from '@foo/design/static/img/logo.svg' (imported as 'Logo').
Men hvis jeg kopierer/limer inn svg-importlinjen fra MyComponent.js direkte i min rotnavngitte app-komponent:
import { FC } from 'react';
import { ReactComponent as Logo, } from '@foo/design/static/img/logo.svg';
const App: FC = () => {
return (
<Logo />
);
}
export default App;
Dette fungerer, og SVG-en vises som forventet.
Her er også CRA-prosjektets relaterte tsconfig.json-fil:
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}
Hvorfor fungerer ikke ReactComponent CRA-importen når den gjøres fra mitt importerte bibliotek? Hva er den enkleste måten å løse dette problemet på siden @foo/ui kun brukes internt?
Takk
Svar #1
Jeg fant at den eneste løsningen som hjalp meg i en lignende situasjon, er å definere SVG-komponenten inline, ved å bruke https://svg2jsx.com/ for å forberede komponenten.
Så, i ditt tilfelle, vil du ikke kunne bruke delte SVG-er fra @foo/design for å lage en wrapper-komponent, men i det minste vil du kunne forberede de delte SVG-komponentene i @foo/ui.
Brukte mye tid, løste det nettopp, så kan ikke forklare hva det underliggende problemet er.