【问题标题】:How to correctly export SVGs in a React component library with TypeScript如何使用 TypeScript 在 React 组件库中正确导出 SVG
【发布时间】:2020-09-05 11:28:20
【问题描述】:

我正在将我们的 React 应用程序的核心组件提取到一个单独的组件库中,以便在其他客户端应用程序中使用。这些组件使用 SVG 图标,通过 babel-loader 已经可以在原始应用程序中使用。

但是,由于组件是用 Typescript 编写的,据我所知,我需要 ts-loader 才能使库正常工作,即使我无法对此进行测试,因为我什至无法编译图书馆。为了能够完全导出 SVG,我还添加了 babel-loaderbabel-plugin-named-asset-import

这是我的项目结构:

.
├── config
│   └── webpack.config.js
├── global.d.ts
├── index.ts
├── package.json
├── package-lock.json
├── src
│   ├── assets
│   │   └── icons
│   │       ├── index.d.ts
│   │       ├── index.ts
│   │       └── upload.svg
│   ├── bar
│   │   └── index.ts
│   └── foo
│       ├── index.ts
│       └── Stuff.ts
└── tsconfig.json

webpack.config.json:

const path = require("path");

module.exports = {
  entry: "./index.ts",
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: {
          loader: "ts-loader",
        },
        exclude: /node_modules/,
      },
      {
        test: /\.(js|mjs|jsx|ts|tsx)$/,
        loader: require.resolve("babel-loader"),
        options: {
          customize: require.resolve(
            "babel-preset-react-app/webpack-overrides"
          ),

          plugins: [
            [
              require.resolve("babel-plugin-named-asset-import"),
              {
                loaderMap: {
                  svg: {
                    ReactComponent: "@svgr/webpack?-svgo,+ref![path]",
                  },
                },
              },
            ],
          ],
        },
      },
    ],
  },
  resolve: {
    extensions: [".tsx", ".ts", ".js"],
  },
};

tsconfig.json:

{
  "include": ["./global.d.ts", "./index.ts", "src/**/*"],

  "compilerOptions": {
    "allowJs": false,
    "jsx": "react",
    "esModuleInterop": true,
    "downlevelIteration": true,
    "declaration": true,
    "noEmit": false,
    "outDir": "dist",
    "moduleResolution": "node",
    "module": "commonjs",
    "target": "es5",
    "lib": ["es5", "es6", "es7", "es2017", "dom"],
    "sourceMap": true,
    "typeRoots": ["./node_modules/@types", "./@types"],
    "resolveJsonModule": true
  }
}

global.d.ts - 我发现这里的declare module 部分完全没有效果,无论有没有它我都会得到相同的结果。

import 'jest-dom/extend-expect';

declare module '*.svg' {
  const content: string;
  export default content;
}

./src/assets/icons/index.ts 应该负责导出所有可用的图标供其他文件导入。

export { ReactComponent as Add } from "./add.svg";

./src/demo/index.ts 包含“使用”此 SVG 的代码:

import { Add } from "../assets/icons";

export default {
  Add,
};

根目录下的index.ts包含相同的内容来演示我的问题的不一致:

import { Add } from "../assets/icons";

export default {
  Add,
};

到目前为止一切顺利,我想,所以我用npx webpack --config ./config/webpack.config.js 运行 webpack,结果整个事情都失败了,并出现了这个错误消息:

ERROR in C:\work\tstest\src\demo\index.ts
[tsl] ERROR in C:\work\tstest\src\demo\index.ts(1,21)
      TS2306: File 'C:/work/tstest/src/assets/icons/index.ts' is not a module.

这让我对几个问题完全困惑:

  1. 有问题的文件怎么不是模块?很高兴知道是什么阻止了 ts-loader 正确识别它
  2. ./src/demo/index.ts./index.ts 在内容上是 100% 相同的。尽管如此,编译适用于一个文件,但不适用于另一个。为什么会这样?这种行为记录在哪里?
  3. 我做错了什么?
  4. 正确的方法是什么?

我想这是因为在 babel-loader 完成它的工作之后,./src/assets/icons/index.ts 看起来不像 ts-loader 想要的那样,但这并不能完全解释如何处理具有相同内容的两个文件不同。

【问题讨论】:

    标签: reactjs typescript webpack babel-loader


    【解决方案1】:

    这是我不了解使用的工具的典型案例。问题出在 tsconfig.json 中:

    "include": ["./global.d.ts", "./index.ts", "src/**/*"]
    

    其中包括tsc启动时项目的所有源文件。这导致 tsc 试图在 webpack 调用 ts-loader 时一次编译所有源文件,包括那些尚未被 @svgr/webpack 处理的文件,从而导致错误。

    解决办法是

    "include": ["./global.d.ts", "src/**/*.d.ts"]
    

    这样,webpack 负责根据其配置的逻辑编译入口点包含的各个源文件,并且 tsc 只看到那些已经被 webpack 处理的定义文件。

    【讨论】:

      猜你喜欢
      • 2023-02-24
      • 2021-12-13
      • 1970-01-01
      • 2021-01-03
      • 1970-01-01
      • 2021-03-10
      • 2021-07-28
      • 2018-05-09
      • 2019-06-27
      相关资源
      最近更新 更多