Import SVG Assets

Modern.js supports import SVG assets and transform SVG into React components or URLs.

What is SVG

SVG stands for Scalable Vector Graphics. It is a type of image format that uses vector graphics to represent images. Vector graphics are different from raster graphics, which are made up of pixels. Instead, vector graphics use geometric shapes, lines, and curves to represent images. Because vector graphics are not made up of pixels, they can be scaled to any size without losing resolution or quality.

Import SVG in JS file

Default Import

If you use the default import to reference SVG, it will be treated as a static asset and you will get a URL string:

src/component/Logo.tsx
import logoURL from './static/logo.svg';

console.log(logoURL); // => "/static/logo.6c12aba3.png"

Transform to React Component

When referencing SVG assets in JS files, if the import path includes the ?react suffix, Modern.js will call SVGR to transform the SVG image into a React component:

src/component/Logo.tsx
import Logo from './logo.svg?react';

export default () => <Logo />;
TIP

Modern.js >= 2.48.3 version supports the above usage.

Modern.js also supports the following usage, transforming SVG into a React component by named import ReactComponent:

src/component/Logo.tsx
import { ReactComponent as Logo } from './static/logo.svg';

export default () => <Logo />;

Modify the Default Export

You can modify the default export of SVG files through the output.svgDefaultExport config. For example, set the default export as a React component:

export default {
  output: {
    svgDefaultExport: 'component',
  },
};

Then import the SVG, you'll get a React component instead of a URL:

src/component/Logo.tsx
import Logo from './static/logo.svg';

export default () => <Logo />;

Import SVG in CSS file

When import an SVG in a CSS file, the SVG is treated as a normal static asset and you will get a URL:

.logo {
  background-image: url('../static/logo.svg');
}

Assets Processing

When SVG is imported not as a React component but as a normal static asset, it is processed exactly the same as other static assets, and it is also affected by rules such as assets inlining and URL prefixing.

Please read the Import Static Assets section to understand the processing rules for static assets.

Disable SVGR Processing

By default, when an SVG resource is referenced in a JS file, Modern.js will call SVGR to convert the SVG into a React component. If you are sure that all SVG resources in your project are not being used as React components, you can turn off this conversion by setting disableSvgr to true to improve build performance.

export default {
  output: {
    disableSvgr: true,
  },
};

Add type declaration

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 a type declaration file for the SVG asset, please create a src/global.d.ts file, and add the following type declaration:

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;
}

If you set svgDefaultExport to 'component', then change the type declaration to:

declare module '*.svg' {
  export const ReactComponent: React.FunctionComponent<
    React.SVGProps<SVGSVGElement>
  >;

  export default ReactComponent;
}

After adding the type declaration, if the type error still exists, you can try to restart the current IDE, or adjust the directory where global.d.ts is located, making sure the TypeScript can correctly identify the type definition.

Modify the SVGR configuration

When SVGR is enabled, its default configuration is as follows:

{
  svgo: true,
  svgoConfig: {
    plugins: [
      {
        name: 'preset-default',
        params: {
          overrides: {
            removeViewBox: false,
          },
        },
      },
      'prefixIds',
    ],
  },
}

If you need to modify the SVGR configuration, you can do the following:

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;
        });
    },
  },
};