Babel.js 使用SVG作为来自专用React UI库的React组件-(CRA)在Webpack 5崩溃的React应用程序内

k4ymrczo  于 2022-12-08  发布在  Babel
关注(0)|答案(1)|浏览(222)

我用CRA创建了一个UI库,这个库发布在npm上,库中的组件使用SVG,我使用的语法是

import {ReactCompoent as Icon} from 'assets / icon'

我想在我的主应用中使用我使用react 17.0.2和webpack 5创建的库。我将加载器添加到Webpack中,我可以将svg用作主应用中的组件,如-

import CalendarIcon from './Calendar.svg'

而且很管用。
在安装库并导入使用SVG作为ReactComponent的组件后:

import {BadgeBox} from '@privatelib/ui/lib/src'

应用程序崩溃。错误为:

WARNING in ./node_modules/@privatelib/ui/lib/src/components/BadgeBox/index.js 107:1697-1707

export 'ReactComponent' (imported as 'CloseIcon') was not found in '../../assets/sm/xsmall-icon.svg' (possible exports: default)

我的React用户界面库:

组成部分:

import { ReactComponent as CloseIcon } from '../../assets/sm/x-small-icon.svg';

tsconfig文件:

{
  "compilerOptions": {
    "target": "es5",
    "baseUrl": "src",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext",
      "es5",
      "es2015",
      "es2016"
    ],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "react-jsx",
    "sourceMap": true,
    "declarationMap": true,
    "declaration": true,
    "outDir": "lib"
  },
  "types": ["cypress", "cypress-file-upload"],
  "include": [
    "src/**/*",
    "custom.d.ts",
  ],
}

我的主应用程序:
网络套件配置:

const HtmlWebPackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

const deps = require('./package.json').dependencies;

module.exports = {
  output: {
    filename: '[name].[contenthash:20].esm.js',
    chunkFilename: '[name].[chunkhash:20].esm.js',
    hashFunction: 'xxhash64',
    pathinfo: false,
    crossOriginLoading: false,
    clean: true,
    publicPath: 'auto',
  },

  resolve: {
    extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
  },

  devServer: {
    port: 3011,
    historyApiFallback: true,
  },

  module: {
    rules: [
      {
        test: /\.m?js/,
        type: 'javascript/auto',
        resolve: {
          fullySpecified: false,
        },
      },
      {
        test: /\.(css|s[ac]ss)$/i,
        use: ['style-loader', 'css-loader', 'postcss-loader'],
      },
      {
        test: /\.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
      {
        test: /\.svg$/i,
        issuer: /\.[jt]sx?$/,
        use: ['@svgr/webpack'],
      },
      {
        test: /\.(?:ico|gif|png|jpg|jpeg|)$/i,
        type: 'asset/resource',
      },
      {
        test: /\.(woff(2)?|eot|ttf|otf|)$/,
        type: 'asset/inline',
      },
    ],
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'sidebar',
      filename: 'remoteEntry.js',
      remotes: {},
      exposes: {
        './SideBar': './src/components/Sidebar/index.tsx',
      },
      shared: {
        ...deps,
        react: {
          singleton: true,
          requiredVersion: deps.react,
        },
        'react-dom': {
          singleton: true,
          requiredVersion: deps['react-dom'],
        },
      },
    }),
    new HtmlWebPackPlugin({
      template: './src/index.html',
    }),
  ],
};

Babel:

{
  "presets": ["@babel/preset-typescript", "@babel/preset-react", "@babel/preset-env"],
  "plugins": [
    ["@babel/transform-runtime"],
    "babel-plugin-styled-components"
  ]
}
mzmfm0qo

mzmfm0qo1#

TL;DR The right way of importing default exports in JavaScript is

import CloseIcon from '../../assets/sm/x-small-icon.svg';

In JavaScript, the import syntax is as follows:

import defaultExport from "module-name";
import { export1 } from "module-name";

which means:

  • "import the component of module-name that is exported as default and use it as defaultExport "
  • "import the component of module-name that is exported as export1 and use it as such"

According to the SVGR docs (1),
Please note that by default, @svgr/webpack will try to export the React Component via default export if there is no other loader handling svg files with default export.
Translated to plain JavaScript-English, this means "as long as you do not tell us otherwise, we will export the ReactComponent as the default ". Since you are not configuring anything different in your webpack config and trying to import the ReactComponent, I assume it should be available as the default export. Therefore, the right way to importing it is

import CloseIcon from '../../assets/sm/x-small-icon.svg';

This is just a guess, of course you can proof me wrong. (2)

  1. I assume you are using @svgr/webpack again, as in your previous question.
  2. Since this proposal is deducted from the docs and your code, there might be other factors involved that I'm not aware of.

相关问题