40

Tried to use this library: vite-plugin-react-svg

and had no success by importing it like:

import { ExternalLink } from 'assets/svg/link-external.svg?component';

Are there any workarounds for this issue?

The error i got before was the following:

import { ReactComponent as ExternalLink } from 'assets/svg/link-external.svg';

//Uncaught SyntaxError: 
  The requested module '/src/assets/svg/link-external.svg?import'
  does not provide an export named 'ReactComponent'
Kakiz
  • 1,145
  • 1
  • 9
  • 18

10 Answers10

72

Update 2023

Use vite-plugin-svgr

  1. Add SVGR to the project

yarn add vite-plugin-svgr

  1. Register the plugin SVGR to vite in vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import svgr from 'vite-plugin-svgr' 

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(), 
    svgr({ 
      svgrOptions: {
        // svgr options
      },
    }),
  ], 
})
  1. In App.tsx import SVG as React Component :
import { ReactComponent as ReactLogo } from './assets/react.svg'

<ReactLogo />

Stackblitz Examples:

References:

Bonus:


Note: Previous plugin @honkhonk/vite-plugin-svgr is deprecated (thanks Richard Fernandez for pointing it)

flydev
  • 4,327
  • 2
  • 31
  • 36
  • 3
    While the proposed specific plugin version didn't work me, this one did: `yarn add -D vite-plugin-svgr`, combined with this syntax: `import { ReactComponent as Happy } from './assets/svg/happy.svg'`. This practically emulates how react-scripts does it, and might be useful for anyone migrating from react-scripts to vite. – miek Jan 29 '22 at 08:53
  • @miek no luck with either, and my approach in the answer below – Nikos Jul 04 '22 at 13:39
  • 1
    Careful of this above answer... the `@honkhonk` seems to be an archived fork. Best to take from the official source: https://www.npmjs.com/package/vite-plugin-svgr – Richard Fernandez Jan 16 '23 at 07:30
  • 1
    I'm going to insist that people actually **run their code** before psoting here. The syntax `svgr({ svgrOptions({ // svgr options }), })`, (here in one line) is worng! Not only `svgrOptions` is not a function, but also you can't just open `{}`s and dump stuff inside like it's a Python set, or something. What you wanted to say was `svgr({ svgrOptions: { // svgr options }, })`. – Ricardo Mar 09 '23 at 13:30
19

Anyone having issues with the accepted answer, try the solution described in this package: https://www.npmjs.com/package/vite-plugin-svgr

import { ReactComponent as Logo } from './logo.svg'

For some reason, I couldn't build using the accepted answer

Gal Zakay
  • 286
  • 2
  • 4
  • Thanks. Best answer for working with SVGs in the same way as CRA. Worked like a charm with styled-components. – Nelson Fleig Mar 31 '22 at 02:07
  • 1
    Why this is not the accepted answer is unexplainable. Please refer to my comment in the... _accepted_ answer for why that's wrong and yours points into the right direction. – Ricardo Mar 09 '23 at 13:32
9

You should use @svgr/rollup instead of vite-plugin-svgr. vite-plugin-svgr is not a good choice, because it doesn't support svgo, and it use esbuild to transform some svg code, it may have some problem in es5 environment.

The worst thing is vite-plugin-svgr can't add svgo plugin, see this issue: https://github.com/pd4d10/vite-plugin-svgr/issues/49.

npm install @svgr/rollup -D
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import svgr from '@svgr/rollup';

export default defineConfig({
  plugins: [react(), svgr()]
});
oxygen
  • 129
  • 1
  • 9
8

yarn add -D vite-plugin-svgr will be the best choice as it keeps being maintained.

// vite.config.js
import svgr from 'vite-plugin-svgr'

export default {
  plugins: [svgr()],
}
import { ReactComponent as Logo } from './logo.svg'

Also you can import as default by setting up this config option in vite.config.js.

svgr({
  exportAsDefault: true
})
// now you can import as default
import Logo from './logo.svg'

But notice that it will overrides the default behavior of Vite which exports the URL as default.


If you have any typescript issues, there is also a declaration helper for better type inference

/// <reference types="vite-plugin-svgr/client" />
myquertykeyboard
  • 427
  • 6
  • 19
3

I migrated from CRA to Vite and was facing this problem, I followed the above steps but did not work for me. I went to the official documentation of Vite and found that I needed to add

 "types": ["vite/client"],

inside my tsConfig.json file which will then enable the support for svgs and couple of other things.

More information - https://vitejs.dev/guide/features.html#typescript

Chipsy
  • 166
  • 2
  • 10
1

I was able to solve this issue after installing this package:

npm i vite-plugin-svgr

// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import svgr from 'vite-plugin-svgr'; // make sure to import it

export default defineConfig({
    plugins: [react(), svgr()],
});

// App.jsx
import {ReactComponent as ExternalLink} from './assets/svg/link-external.svg';

<ExternalLink />
AmkE
  • 11
  • 2
1

Use @svgx/vite-plugin-react

install it

npm i @svgx/vite-plugin-react

and include it in your vite.config.js file

import { defineConfig } from "vite";
import svgx from "@svgx/vite-plugin-react";

export default defineConfig(async () => {
  return {
    plugins: [
      svgx()
    ],
  };
});

and then import your svg as react component

import MyIcon from "./icon.svg?component";

You can import the svg as "component" or "url" or "raw"

See its documentation on github

The best part about this plugin is that you can import the svg files dynamically. ie: if you want to import an svg using a variable name you can do that like this:

import importVars from "@svgx-dir:/path/to/directory";

export default function (props) {
  const MyIcon = importVars(props.iconName);
  return (
    <div>
      <MyIcon color="#FF5733" />
    </div>
  );
}

Now you can pass a variable to importVars function to import an svg dynamically.

1

I had the same issue but wanted to avoid using external packages.

following @user8659363's answer -

My solution was to create a new file under src directory, and reference it to vite's types -

src/vite-env.d.ts

content:

/// <reference types="vite/client" />

Here you can see the full list of supported modules/extensions - https://github.com/vitejs/vite/blob/32c5a9a618b625c707703ede05215e499ee1744b/packages/vite/client.d.ts#L129

molaga
  • 160
  • 1
  • 8
  • Thanks for your answer. i also been able to import SVG's in vite without using external packages, maybe they patched it. – Kakiz May 24 '23 at 14:20
0

You can avoid svgr by importing like this an assigning to an img

import logo from "./logo-login.svg"
<img src={logo} className="w-24 inline-block" alt="logo" />
Nikos
  • 7,295
  • 7
  • 52
  • 88
0

I had the same issue as well, the npm vite-plugin-svgr documentation explains it very well in how to add it and use it with vite.

Fallen
  • 3
  • 1
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – devpolo Feb 19 '23 at 18:35