Library / SDK
pd4d10/vite-plugin-svgr avatar
pd4d10/vite-plugin-svgr

vite-plugin-svgr and the ?react suffix that turns SVG files into components

Vite plugin to transform SVGs into React components

755 stars74 forksTypeScriptMIT

At a glance

What is it?
vite-plugin-svgr is a small Vite plugin that resolves SVG imports written with a ?react suffix into React components, delegating the actual conversion to svgr and keeping the compiler step configurable for both esbuild and oxc based builds.
Who is it for?
Adopt vite-plugin-svgr when a Vite project needs SVG files to arrive as React components and the team is willing to keep the ?react suffix in import paths. Skip it if the project does not build with Vite, or if SVG assets need to be optimised outside the bundler.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The ?react suffix is the entire public interface

The whole public surface of this package is a question mark in an import path. The README says SVG files can be imported as React components once the plugin is registered, and the example it gives ends the path with ?react. Everything else in the package exists to make that one import resolve to a component instead of a file.

The conversion work is delegated. The README states the plugin uses svgr, and package.json confirms the dependency set: @svgr/core and @svgr/plugin-jsx are runtime dependencies, while @rollup/pluginutils is there to supply the filter helpers Vite plugins use to decide which module ids they claim. The plugin itself is thin. package.json lists version 5.2.0, publishes an ESM entry at ./dist/index.js and a CommonJS entry at ./dist/index.cjs, and declares a peer dependency on vite >=3.0.0. There is no separate loader to register and no asset pipeline change to negotiate.

Installing the plugin and making the first ?react import

The plugin only affects the build, so it belongs in dev dependencies. The README lists the same package under all three common package managers:

sh
# npm
npm install --save-dev vite-plugin-svgr

# yarn
yarn add -D vite-plugin-svgr

# pnpm
pnpm add -D vite-plugin-svgr

Next, register it in the Vite config file:

js
// vite.config.js
import svgr from "vite-plugin-svgr";

export default {
  // ...
  plugins: [svgr()],
};

The call takes an options object that can be empty, so svgr() is enough for the default behaviour. With the plugin in place, an SVG file can be imported as a component:

js
import Logo from "./logo.svg?react";

A reader who follows those three steps should see the original artwork render as a React component, and the editor should offer component props rather than a string path for the asset.

svgrOptions, esbuildOptions and oxcOptions carry three different layers

svgr() accepts a single options object whose keys divide into three separate transformation layers. svgrOptions passes through to svgr, with the README pointing at the svgr options documentation. esbuildOptions covers the jsx to js transform, and oxcOptions is described as being used by rolldown and vite 8+.

Carrying both compiler hooks is not redundancy. The plugin ships with two code generators so a single configuration file can survive a change of bundler generation, which matters because the esbuild path and the oxc path are not interchangeable. The generation of the component and the compilation of that component are separate concerns, and the options object keeps them apart.

A practical consequence is that one svgr() call can hold both the component generation settings and the compiler settings for whichever bundler the project uses, rather than requiring a fork or a second plugin when the project moves to a rolldown based or vite 8+ setup.

TypeScript needs one reference line in vite-env.d.ts

The plugin ships a declaration file for the client side of the import. package.json exposes it under the ./client export path, pointing at ./client.d.ts, and client.d.ts sits at the top level of the repository. Without it, TypeScript has no way to know that an import ending in ?react returns a component rather than a string, so editor tooling falls back to generic module resolution.

The fix is a single line added to vite-env.d.ts:

ts
/// <reference types="vite-plugin-svgr/client" />

That reference pulls the ambient types into the project so props are inferred on the imported component. The README frames this as a helper for better type inference rather than a requirement for the transform itself, so a JavaScript project can leave it out. A TypeScript project that wants prop hints on SVG component imports needs it.

include and exclude are minimatch filters, and exclude starts empty

Which files the plugin claims is controlled by two minimatch patterns. The README describes include as the pattern for the files in the build the plugin should include, and gives its default as "**/*.svg?react". exclude is the pattern for files the plugin should ignore, and the README notes that by default no files are ignored, with the default value shown as an empty string.

The consequence for a shared codebase is direct. A monorepo package that publishes icons under a path alias can pull that alias into the transform by adding the pattern to include, and can keep a legacy folder of hand-tuned SVG assets out of the pipeline by listing it in exclude. Leaving exclude empty means every suffixed import in the project is transformed, including fixtures in test files and story files that happen to end in ?react.

SVG optimisation is opt-in and needs a separate install

Optimisation is not part of the default path. The README says SVGO can be enabled by installing @svgr/plugin-svgo and then listing it in the svgr plugins array.

The order of that array is the part worth copying exactly:

js
svgr({
  svgrOptions: {
    plugins: ["@svgr/plugin-svgo", "@svgr/plugin-jsx"],
    svgoConfig: {
      floatPrecision: 2,
    },
  },
  // ...
});

The optimiser runs before the jsx plugin, and the SVGO settings travel under svgrOptions as svgoConfig rather than as a key of this plugin. The floatPrecision: 2 value shown there controls how many decimal places survive in the path data of the optimised file. Because the optimiser is a separate package, the plugin gives you no optimisation behaviour until that dependency is present.

A peer range of vite >=3.0.0 backed by seven installed Vite majors

Version support is the part of this package with the most visible evidence behind it. peerDependencies declares vite >=3.0.0, and the devDependencies go further by aliasing several Vite majors into one install at once: vite3 aliased to npm:[email protected], vite4 to 4.5.14, vite5 to 5.4.21, vite6 to 6.4.1, vite7 to 7.3.1 and vite8 to 8.0.3. A dedicated script, test:compat, runs node scripts/test-vite-compat.js, and separate entries exist for the general suite and for a process level end to end file.

The release history is dense at the start of 2026. v5.0.0 was published on 2026-03-28, v5.1.0 on 2026-04-02 and v5.2.0 on 2026-04-02. The last push to the repository was on 2026-04-02. That is the whole maintenance record for the project: the last push was on 2026-04-02, and the newest published version is v5.2.0.

Where this plugin is the wrong tool

This is a narrow package, and the narrowness is the design. It maps suffixed SVG imports to components inside a Vite build. A project that does not build with Vite cannot use it, since the peer dependency is on vite >=3.0.0 and the ?react convention is honoured by the Vite module pipeline.

The alternative is to drive @svgr/core directly, since that is the dependency doing the work here. The difference in approach is where the transform sits. Through this plugin, SVG handling lives inside the Vite module graph and is triggered by the query string on the import, so it applies only to files imported with that suffix. Calling the svgr library from your own script moves conversion outside the bundler, so a generated component no longer depends on a running dev server, but the automatic coverage of every import site is gone and regeneration becomes your own concern.

A second limit is that the transform happens at import time inside a running Vite process. The README documents no cache setting and no precompile command for a CI step, so a pipeline that needs assets converted before the build starts has no documented route through this plugin.

Editorial conclusion

Adopt vite-plugin-svgr when a Vite project needs SVG files to arrive as React components and the team is willing to keep the ?react suffix in import paths. Skip it if the project does not build with Vite, or if SVG assets need to be optimised outside the bundler. Before committing, check that the Vite version in the project sits inside the >=3.0.0 peer range, and weigh the fact that the last push was on 2026-04-02 with the newest release being v5.2.0.

Frequently asked questions

How do I install vite-plugin-svgr and import an SVG as a React component?

Install the package as a dev dependency with npm, yarn or pnpm, then add svgr() to the plugins array in vite.config.js. After that, import the file with a ?react suffix, for example import Logo from "./logo.svg?react".

Does vite-plugin-svgr work with TypeScript?

Yes, through a declaration helper shipped as client.d.ts and exposed under the ./client export path. Add /// <reference types="vite-plugin-svgr/client" /> to vite-env.d.ts so editors infer props on SVG component imports.

How do I enable SVG optimisation in vite-plugin-svgr?

Install @svgr/plugin-svgo and list it inside svgrOptions.plugins ahead of @svgr/plugin-jsx. SVGO settings such as floatPrecision go under svgrConfig within svgrOptions.

Which Vite versions does vite-plugin-svgr support?

The peer dependency declares vite >=3.0.0, and the development dependencies install aliased copies of vite3 through vite8 to exercise that range. A test:compat script runs scripts/test-vite-compat.js against it.

How do I stop vite-plugin-svgr from transforming some SVG files?

Use the exclude option, which takes a minimatch pattern or an array of patterns for files the plugin should ignore. By default no files are ignored, and include defaults to "**/*.svg?react".

Official sources

  1. Issues
  2. License: MIT
  3. pd4d10/vite-plugin-svgr on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pd4d10-vite-plugin-svgr.svg)](https://hysenlabs.com/projects/pd4d10-vite-plugin-svgr)

Was this useful?