今天聊聊@svgr/webpack遇到的坑

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情

一、问题场景

这些天做一件很恶心的事,把项目A和项目B 整合到一起,然后我们以项目A为住,B为副来进行 merge

B项目中,有大量 img 引入 svg 的图片的地方,而项目A中svg是以组件的方式引入的,导致以前那种方式的 svg 都不能显示了。下图是项目A中的 svg 配置:

{
    test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
    issuer: /\.([jt])sx?$/,
    use: ['@svgr/webpack'],
},

复制代码

二、问题模拟

我们现在自己通过create-react-app来搭建一个项目,然后执行npm run eject来暴露我们的 webpack 的配置。我们可以看到 svg 的相关配置如下:

{
  test: /\.svg$/,
  use: [
    {
      loader: require.resolve('@svgr/webpack'),
      options: {
        prettier: false,
        svgo: false,
        svgoConfig: {
          plugins: [{ removeViewBox: false }],
        },
        titleProp: true,
        ref: true,
      },
    },
    {
      loader: require.resolve('file-loader'),
      options: {
        name: 'static/media/[name].[hash].[ext]',
      },
    },
  ],
  issuer: {
    and: [/\.(ts|tsx|js|jsx|md|mdx)$/],
  },
},
复制代码

然后我们在组件中引入 svg 图片:

import React from 'react';
import LogoUrl from './logo.svg'

const App = () => {
  console.log(1111, LogoUrl)
  console.log(2323, require('./logo.svg'))
  return (
      <div>
        <img src={require('./logo.svg').default} width={40} height={40} alt="" />
        <img src={LogoUrl} alt="" />
      </div>
  )
}
export default App;
复制代码

image.png 大家可以留意下我打印的东西,到这里应该都没有什么问题;然后我们修改我们的 webpack 配置和项目A一样,重启再来看页面会怎样? image.png 这时我们的图片都显示不了的了~

我们修改为组件方式引入:

import React from 'react';
import LogoUrl from './logo.svg'

+ import Logo from './logo.svg'

const App = () => {
  console.log(1111, LogoUrl)
  console.log(2323, require('./logo.svg'))
  return (
      <div>
        <img src={require('./logo.svg').default} width={40} height={40} alt="" />
        <img src={LogoUrl} alt="" />
+        <Logo />
      </div>
  )
}
export default App;
复制代码

image.png 现在模拟出我遇到的问题:项目B 中 img 引入的方式就不能显示了~

三、解决问题

SVGR 是将 SVG 转换为 React 组件的通用工具。

现在我需要的是将一部分 SVG 作为静态资源的url,一部分作为 React组件。官方说的是最简单的方法是将 resourceQuery用于两种类型中的一种。

{
    test: /\.svg$/i,
    type: 'asset',
    resourceQuery: /url/, // *.svg?url
},
{
    test: /\.svg$/i,
    issuer: /\.[jt]sx?$/,
    resourceQuery: { not: [/url/] }, // exclude react component if *.svg?url
    use: ['@svgr/webpack'],
},
复制代码

你可能会问resourceQuery是什么,你可以自己去查找。这里我们简单说一下,比如上面的配置,我们在引入svg 图片 使用 ×××.svg?url 这种形式的时候,那么我们通过 import 引入的模块参数就符合它这个要求,我们就可以通过 img 引入显示。

修改一下代码:

import React from 'react';
import LogoUrl from './logo.svg?url'
import Logo from './logo.svg'

const App = () => {
  return (
      <div>
        <img src={LogoUrl} alt="" width={40} height={40} />
        <Logo width="140" height="140" />
      </div>
  )
}
export default App;
复制代码

image.png

完结,撒花~

猜你喜欢

转载自juejin.im/post/7084147998376574990