一起养成写作习惯!这是我参与「掘金日新计划 · 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;
复制代码
大家可以留意下我打印的东西,到这里应该都没有什么问题;然后我们修改我们的 webpack 配置和项目A一样,重启再来看页面会怎样? 这时我们的图片都显示不了的了~
我们修改为组件方式引入:
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;
复制代码
现在模拟出我遇到的问题:项目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;
复制代码
完结,撒花~