如何使 svg 反应组件从外部模块导入与 create-react-app 一起使用?

Sou*_*euh 5 javascript svg typescript reactjs create-react-app

语境

为了使一些代码部分可以在许多 React 项目中重复使用,我有以下项目结构:

  1. @foo/design:包含设计内容,例如原始 svg 图像
  2. @foo/ui:基于 Create React App 的常用组件的 React 库
  3. @foo/project:最终的 CRA 项目使用foo/ui

图书馆

该foo/ui库导出一些从以下位置导入 svg 图像的组件@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;
Run Code Online (Sandbox Code Playgroud)

该组件在相关的 Storybook 实例上完美运行@foo/ui,并使用tsc如下方式进行编译:

// 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;
Run Code Online (Sandbox Code Playgroud)

这也是相关tsconfig.json文件:

{
  "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"
  ],
}
Run Code Online (Sandbox Code Playgroud)

项目导入

在 上@foo/project,我添加了@foo/ui依赖项,@foo/design并安装了该包( 需要@foo/ui)。

我这样使用我的组件:

import { FC } from 'react';
import { MyComponent } from '@foo/ui'

const App: FC = () => {
  return (
    <MyComponent />
  );
}

export default App;
Run Code Online (Sandbox Code Playgroud)

但这会产生以下错误:

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').
Run Code Online (Sandbox Code Playgroud)

MyComponent.js但是,如果我直接从根应用程序组件上复制/粘贴 svg 导入行:

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').
Run Code Online (Sandbox Code Playgroud)

这有效并且 svg 按预期显示。

这也是 CRA 项目相关tsconfig.json文件:

import { FC } from 'react';
import { ReactComponent as Logo, } from '@foo/design/static/img/logo.svg';

const App: FC = () => {
  return (
    <Logo />
  );
}

export default App;
Run Code Online (Sandbox Code Playgroud)

为什么ReactComponent从我导入的库完成 CRA 导入后不起作用?解决这个问题的最简单方法是什么(@foo/ui仅在内部使用)?

谢谢

Eug*_*nko 0

我发现唯一的解决方法可以帮助我解决类似的情况 - 内联定义 SVG 组件,使用https://svg2jsx.com/准备组件。

因此,就您的情况而言,您将无法使用共享 SVG 来@foo/design创建包装器组件,但至少您可以在@foo/ui.

花了很多时间,最近才解决它,所以无法解释根本问题是什么。