By default, Rsbuild treats SVG files as static assets. For processing rules, see Static assets.
With the SVGR plugin, Rsbuild supports transforming SVG to React components via SVGR.
You can install the plugin using the following command:
npm add @rsbuild/plugin-svgr -D
You can register the plugin in the rsbuild.config.ts
file:
import { pluginReact } from '@rsbuild/plugin-react';
import { pluginSvgr } from '@rsbuild/plugin-svgr';
export default {
plugins: [pluginReact(), pluginSvgr()],
};
After registering the plugin, when you import an SVG in a JavaScript file, if the imported path includes the ?react
suffix, Rsbuild will call SVGR to transform the SVG into a React component.
import Logo from './logo.svg?react';
export const App = () => <Logo />;
If the imported path doesn't include the ?react
suffix, the SVG will be treated as a normal static asset and you will get a URL string or base64 URL. See Static assets.
import logoURL from './static/logo.svg';
console.log(logoURL); // => "/static/logo.6c12aba3.png"
@rsbuild/plugin-svgr
supports named imports for ReactComponent
when using SVGR. You need to set svgrOptions.exportType to 'named'
:
pluginSvgr({
svgrOptions: {
exportType: 'named',
},
});
import { ReactComponent as Logo } from './logo.svg';
export const App = () => <Logo />;
@rsbuild/plugin-svgr
also supports default imports and mixed imports:
'default'
.To customize the compilation behavior of Svgr, use the following options.
type PluginSvgrOptions = {
/**
* Configure SVGR options.
*/
svgrOptions?: import('@svgr/core').Config;
/**
* Whether to allow the use of default import and named import at the same time.
* @default false
*/
mixedImport?: boolean;
};
Modifies the options of SVGR, the passed object will be deep merged with the default value. See SVGR - Options for details.
import('@svgr/core').Config
const defaultSvgrOptions = {
svgo: true,
svgoConfig: {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false,
},
},
},
'prefixIds',
],
},
};
pluginSvgr({
svgrOptions: {
svgoConfig: {
datauri: 'base64',
},
},
});
When you set svgoConfig.plugins
, the configuration for plugins with the same name is automatically merged. For example, the following configuration will be merged with the built-in preset-default
:
pluginSvgr({
svgrOptions: {
svgoConfig: {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
cleanupIds: false,
},
},
},
],
},
},
});
The merged svgoConfig
will be:
const mergedSvgoConfig = {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: true,
cleanupIds: false,
},
},
},
'prefixIds',
],
};
Set the export type of SVG React components.
'default' | 'named'
undefined
exportType
can be set as:
default
: use default export.named
: use ReactComponent
named export.For example, set the default export of SVG file as a React component:
pluginSvgr({
svgrOptions: {
exportType: 'default',
},
});
Then import the SVG, you'll get a React component instead of a URL:
import Logo from './logo.svg';
console.log(Logo); // => React Component
At this time, you can also specify the ?url
query to import the URL, for example:
import logo from './logo.svg?url';
console.log(logo); // => asset url
When svgrOptions.exportType
is set to 'default'
, the named imports (ReactComponent) cannot be used.
boolean
false
Whether to enable mixed import, allowing to use default import and named import at the same time.
Mixed import is usually used with svgrOptions.exportType: 'named'
, for example:
pluginSvgr({
mixedImport: true,
svgrOptions: {
exportType: 'named',
},
});
At this time, the imported SVG file will export both URL and the React component:
import logoUrl, { ReactComponent as Logo } from './logo.svg';
console.log(logoUrl); // -> string
console.log(Logo); // -> React component
When mixedImport
is enabled, svgrOptions.exportType
defaults to 'named'
if not explicitly configured.
We recommend using ?react
to convert an SVG into a React component rather than relying on mixed imports, which have the following limitations:
RegExp
/react/
Used to custom the query suffix to match SVGR transformation.
For example, if you need to match import paths with the ?svgr
suffix:
pluginSvgr({
query: /svgr/,
});
import Logo from './logo.svg?svgr';
export const App = () => <Logo />;
undefined
Exclude some SVG files, they will not be transformed by SVGR.
For example, if a project includes a.svg
and b.svg
, you can add b.svg
to exclude:
pluginSvgr({
svgrOptions: {
exportType: 'default',
},
exclude: /b\.svg/,
});
When imported, a.svg
will be transformed into a React component, while b.svg
will be treated as a regular static asset:
import component from './a.svg';
import url from './b.svg';
console.log(component); // => React component
console.log(url); // => resource url
undefined
Exclude some modules, the SVGs imported by these modules will not be transformed by SVGR.
For example, if your project contains page-a/index.ts
and page-b/index.ts
, you can add page-b
to excludeImporter:
pluginSvgr({
svgrOptions: {
exportType: 'default',
},
excludeImporter: /\/page-b\/index\.ts/,
});
import Logo from './logo.svg';
console.log(Logo); // => React component
import url from './logo.svg';
console.log(url); // => Resource url
The query in the module path has a higher priority than exclude
and excludeImporter
. For example, if a module is excluded, adding ?react
can still make it transformed by SVGR.
When you reference an SVG asset in TypeScript code, TypeScript may prompt that the module is missing a type definition:
TS2307: Cannot find module './logo.svg' or its corresponding type declarations.
To fix this, you need to add type declaration for the SVG assets, please create a src/env.d.ts
file, and add the type declaration.
declare module '*.svg' {
const content: string;
export default content;
}
declare module '*.svg?react' {
const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
export default ReactComponent;
}
svgrOptions.exportType
is 'default'
, set the type declaration to:declare module '*.svg' {
const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
export default ReactComponent;
}
declare module '*.svg?react' {
const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
export default ReactComponent;
}
svgrOptions.exportType
is 'named'
, set the type declaration to:declare module '*.svg' {
export const ReactComponent: React.FunctionComponent<
React.SVGProps<SVGSVGElement>
>;
}
declare module '*.svg?react' {
const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
export default ReactComponent;
}
svgrOptions.exportType
is 'named'
, and mixedImport
is enabled, set the type declaration to: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;
}
After adding the type declarations, if the type error still exists, you can try to restart the IDE, or adjust the directory where env.d.ts
is located, making sure that TypeScript can correctly identify the type definition.