背景
最近升级项目到umi4时候,发现原先svg-sprite-loader配置不生效,运行时xlink:href变成了'/static/xxx.svg',导致无法展示对应图标,在svg的symbol里也找不到需要引入的图标......
问题复现
可以看到需要加载进来的图标,并没有展示出来,取而代之的是对应静态资源地址,初步怀疑是把svg当作静态资源移动到其他目录了,没有走svg-sprite-loader。
简单使用
安装
yarn add svg-sprite-loader -D
基本使用
通过svg-sprite-loader配置,可以给svg上增加class、style等属性,可以方便的控制元素宽高、fill、stroke等,比如hover时颜色切换,主要用在图标的展示上。当然,用svgr也可以做。
import logo from "../images/logo.svg";
export default function HomePage() {
return (
<div>
<svg width="20" height="20">
<use xlinkHref={logo} fill="#fff" />
</svg>
</div>
);
}
也可以把svg这一部分封装成组件,接收传进来的link和其他props,像这样
const Icon = ({link, props}) => (
<svg {...props}>
<use xlinkHref={link} />
</svg>
)
配置
这里在src目录下,创建images目录来放置图标,如果不是在images目录下存放图标,那需要修改下面配置文件里对应正则。
umi3配置
chainWebpack(config) {
config.module.rule('svg').exclude.add(/images/);
config.module
.rule('svg-sprite')
.test(/\.svg$/i)
.use('svg-sprite-loader')
.loader(require.resolve('svg-sprite-loader'))
.options({
symbolId: 'icon-[name]-[contenthash:5]',
runtimeCompat: true,
})
.end();
},
umi4配置
chainWebpack(config) {
config.module
.rule("svg")
.exclude.add(/images/)
.end();
config.module
.rule("svgr")
.exclude.add(/images/)
.end();
config.module.rule("asset").exclude.add(/images/);
config.module
.rule("svg-sprite")
.test(/\.svg$/i)
.use("svg-sprite-loader")
.loader(require.resolve("svg-sprite-loader"))
.options({
symbolId: "icon-[name]-[contenthash:5]",
runtimeCompat: true,
})
.end()
// 如果不需要,可以不添加svgo,这里是从umi配置复制来的
.use("svgo-loader")
.loader(require.resolve("@umijs/bundler-webpack/compiled/svgo-loader"))
// options这里配置和下面svgo配置相同即可
.options({ configFile: false });
},
svgr: {},
svgo: {},
总结
umi4和umi3对比,在svg处理方面有一些调整,支持配置svgo、svgr,但针对静态资源的处理也影响到了svg,需要先关闭 静态资源规则 对svg目录处理,再去配置需要自定义的loader。
// https://github.com/umijs/umi/blob/master/packages/bundler-webpack/src/config/assetRules.ts
...省略部分
rule
.oneOf('image')
.test(/\.(bmp|gif|jpg|jpeg|png)$/)
.type('asset')
.parser({
dataUrlCondition: {
maxSize: inlineLimit,
},
});
const fallback = rule
.oneOf('fallback')
.exclude.add(/^$/) /* handle data: resources */
.add(/\.(js|mjs|cjs|jsx|ts|tsx)$/)
.add(/\.(css|less|sass|scss|styl|stylus)$/)
.add(/\.html$/)
.add(/\.json$/);
if (userConfig.mdx) {
fallback.add(/\.mdx?$/);
}
fallback.end().type('asset/resource');