简体   繁体   English

如何使 svg 从使用 create-react-app 的外部模块导入组件?

[英]How to make svg react component imports from external module working with create-react-app?

Context语境

In order to make some code parts re-usable accross many react project, I have the following project structure:为了使一些代码部分在许多反应项目中可重用,我有以下项目结构:

  1. @foo/design : Containing design stuff such as raw svg images @foo/design :包含设计内容,例如原始 svg 图像
  2. @foo/ui : A react library base on Create React App for common component @foo/ui : 基于 Create React App for common 组件的反应库
  3. @foo/project : A final CRA project using foo/ui @foo/project :使用foo/ui的最终 CRA 项目

The library图书馆

The foo/ui library export some a component that import a svg image from @foo/design : foo/ui库导出一些从@foo/design导入 svg 图像的组件:

// 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;

This component works flawlessly on the related Storybook instance of @foo/ui and is compiled using tsc like this:该组件在@foo/ui的相关 Storybook 实例上完美运行,并使用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;

Here is also the related tsconfig.json file:这里也是相关的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"
  ],
}

The project import项目导入

On @foo/project , I added the @foo/ui dependency, installing the @foo/design package as well (required by @foo/ui ).@foo/project上,我添加了@foo/ui依赖项,同时安装了@foo/design package( @foo/ui需要)。

I use my component that way:我以这种方式使用我的组件:

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

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

export default App;

But this produces the following error:但这会产生以下错误:

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').

However, if I copy/past the svg import line from MyComponent.js directly on my root app component:但是,如果我直接在我的根应用程序组件上从MyComponent.js复制/过去 svg 导入行:

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

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

export default App;

This works and the svg appears as expected.这有效,并且 svg 按预期出现。

Here is also the CRA project related tsconfig.json file:这里也是CRA项目相关的tsconfig.json文件:

{
  "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"
  ]
}

Why the ReactComponent CRA import is not working when it's done from my imported library?为什么ReactComponent CRA 导入在从我导入的库中完成时不起作用? What is the simplest way to solve this problem as @foo/ui is only use internally?由于@foo/ui仅在内部使用,解决此问题的最简单方法是什么?

Thanks谢谢

I found the only workaround helped me in a similar situation - define SVG component inline, using https://svg2jsx.com/ to prepare component.我发现在类似情况下唯一的解决方法可以帮助我 - 使用https://svg2jsx.com/内联定义 SVG 组件来准备组件。

So, in your case, you won't be able to use shared SVG's from @foo/design to create a wrapper component, but at least you'll be able to prepare the shared SVG components in @foo/ui .因此,在您的情况下,您将无法使用来自@foo/design的共享 SVG 来创建包装器组件,但至少您将能够在@foo/ui中准备共享的 SVG 组件。

Spent much time, solved it just recently, so can't explain what's the underlying issue is.花了很多时间,最近才解决它,所以无法解释根本问题是什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM