引用 SVG 资源
Modern.js 支持在代码中引用 SVG 资源,并将 SVG 图片转换为 React 组件或 URL。
什么是 SVG
SVG 是 Scalable Vector Graphics 的缩写,意为可伸缩矢量图形。SVG 是一种用来描述二维矢量图形的 XML-based 格式,可以用来创建可以无限放大或缩小而不失真的图像。因为 SVG 图形是由矢量图形元素组成的,所以可以轻松地在各种尺寸和分辨率下渲染。
在 JS 文件中引用
默认导入
如果你使用默认导入来引用 SVG,它会被当做静态资源来处理,你会得到一个 URL 字符串:
src/component/Logo.tsx
import logoURL from './static/logo.svg';
console.log(logoURL); // => "/static/logo.6c12aba3.png"
转换 React 组件
在 JS 文件中引用 SVG 资源时,如果导入的路径包含 ?react
后缀,Modern.js 会调用 SVGR,将 SVG 图片转换为一个 React 组件:
src/component/Logo.tsx
import Logo from './logo.svg?react';
export default () => <Logo />;
TIP
Modern.js >= 2.48.3 版本支持上述用法。
Modern.js 也支持以下用法,通过具名导入 ReactComponent
来转换 SVG 为 React 组件:
src/component/Logo.tsx
import { ReactComponent as Logo } from './static/logo.svg';
export default () => <Logo />;
修改默认导出
你可以通过 output.svgDefaultExport 配置项来修改 SVG 文件默认导出的内容,比如把默认导出的内容设置为 React 组件:
export default {
output: {
svgDefaultExport: 'component',
},
};
此时再使用默认导入,你会得到一个 React 组件,而不是 URL:
src/component/Logo.tsx
import Logo from './static/logo.svg';
export default () => <Logo />;
在 CSS 文件中引用
在 CSS 文件中引用 SVG 资源时,SVG 会被当做一个普通的静态资源来处理,你会得到一个 URL:
.logo {
background-image: url('../static/logo.svg');
}
静态资源处理
当 SVG 不是作为 React 组件,而是作为一个普通的静态资源被引用时,它的处理逻辑和其他静态资源完全一致,也会受到静态资源内联、URL 前缀等规则的影响。
请阅读 引用静态资源 章节来了解静态资源的处理规则。
禁用 SVGR 处理
默认情况下,在 JS 文件中引用 SVG 资源时,Modern.js 会调用 SVGR,将 SVG 图片转换为一个 React 组件。
如果你确定项目内的所有 SVG 资源都没有当成 React 组件使用时,可以通过将 disableSvgr 设置为 true 来关闭此项转换,以提升构建性能。
export default {
output: {
disableSvgr: true,
},
};
添加类型声明
当你在 TypeScript 代码中引用 SVG 资源时,TypeScript 可能会提示该模块缺少类型定义:
TS2307: Cannot find module './logo.svg' or its corresponding type declarations.
此时你需要为 SVG 资源添加类型声明文件,请在项目中创建 src/global.d.ts
文件,并添加相应的类型声明:
declare module '*.svg' {
export const ReactComponent: React.FunctionComponent<
React.SVGProps<SVGSVGElement>
>;
const content: string;
export default content;
}
declare module '*.svg?react' {
const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
export default ReactComponent;
}
如果你将 svgDefaultExport
设置为 'component'
,则将类型声明修改为:
declare module '*.svg' {
export const ReactComponent: React.FunctionComponent<
React.SVGProps<SVGSVGElement>
>;
export default ReactComponent;
}
添加类型声明后,如果依然存在上述错误提示,请尝试重启当前 IDE,或者调整 global.d.ts
所在的目录,使 TypeScript 能够正确识别类型定义。
修改 SVGR 配置
当启用 SVGR 时,其默认配置如下:
{
svgo: true,
svgoConfig: {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false,
},
},
},
'prefixIds',
],
},
}
如果需要修改 SVGR 配置,可通过如下方式:
export default {
tools: {
bundlerChain: (chain, { CHAIN_ID }) => {
chain.module
.rule(CHAIN_ID.RULE.SVG)
.oneOf(CHAIN_ID.ONE_OF.SVG)
.use(CHAIN_ID.USE.SVGR)
.tap(options => {
// modify svgoConfig
options.svgoConfig.plugins[0].params.overrides.removeUselessDefs = false;
return options;
});
},
},
};