pd4d10 / vite-plugin-svgr

Vite plugin to transform SVGs into React components
MIT License
559 stars 54 forks source link

SSR Compatibility Issue #123

Closed bebeal closed 1 month ago

bebeal commented 3 months ago

Problem

When using SVGR with Vite in a Server-Side Rendering (SSR) configuration, the default type definitions provided by SVGR lead to errors during the server-side rendering process.

Using .svg?react to import SVGs as React components cause "Invalid tag" errors during server-side rendering.

Example

// Using Vite SSR
import React from 'react';
import NodeLogo from './assets/node.svg?react'

export const App = () => {
  return (
    <div>
      <h1>Welcome to my app</h1>
      <NodeLogo width={50} height={50} />
    </div>
  );
}

Error

Error: Invalid tag: /src/assets/node.svg?react
    at startChunkForTag (/Users/bebeal/Prod/vite-amplify/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:2734:13)
    at pushStartGenericElement (/Users/bebeal/Prod/vite-amplify/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:2560:15)
    at pushStartInstance (/Users/bebeal/Prod/vite-amplify/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:2838:18)
    at renderHostElement (/Users/bebeal/Prod/vite-amplify/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5640:18)
    ...

Workaround

A simple workaround is to override the type definitions as follows:

// Defines the type for .svg?url imports to be a string
declare module '*.svg?url' {
  const src: string;
  export default src;
}

// Defines the type for .svg imports to be React components
declare module '*.svg' {
  const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>> & { title?: string };
  export default ReactComponent;
}

Usage

The updated usage works for both react components and urls, without any errors.

// Using Vite SSR
import React from 'react';
import NodeLogo from './assets/node.svg'
import NodeUrl from './assets/node.svg?url'

export const App = () => {
  return (
    <div>
      <h1>Welcome to my app</h1>
      <NodeLogo width={50} height={50} />
      <img src={NodeUrl} alt="Node.js logo" width={50} height={50} />
    </div>
  );
}

I'm open to discussing further and contributing if we can get this functionality to work out of the box. But feel free to address this as you see fit, I just wanted to bring attention to it.

pd4d10 commented 2 months ago

get this functionality to work out of the box.

Sure. Which SSR framework are you using? Could you please provide a minimal reproduction?

bebeal commented 2 months ago

Vite SSR - here's a single page app that can reproduce https://github.com/bebeal/vite-amplify

bebeal commented 1 month ago

closing this issue - I believe the root cause is related to vite https://github.com/vitejs/vite/issues/18034