gregberge / svgr

Transform SVGs into React components 🦁
https://react-svgr.com
MIT License
10.57k stars 421 forks source link

SVG being downloaded client side in a 'server only' component NextJS #883

Open ricardo-fnd opened 1 year ago

ricardo-fnd commented 1 year ago

🐛 Bug Report

In NextJS 13.4.1, SVGs rendered inside a server component are being downloaded client side, when a use client component is present.

'server-only' component

<div>
    <ClientSideComponent /> // using 'use client' directive
    <div>
        <Svg /> // using SVGR (download should happen server side)
    </div>
</div>

The page that renders this server-only component, appears in the network tab with 208kbs because its downloading <ClientSideComponent> (which is client-side, so its okay) and <Svg> (which is a SVG, and this is not okay)

If I comment <ClientSideComponent> and run build && start, the page is not downloaded client-side, not even the SVG. So, my conclusion is that, <ClientSideComponent> client component is triggering the SVG to render client side when its inside an server-only component...

However, when I removed the SVGR library, and installed other SVG to React Component lib, this is not happening. Only the <ClientSideComponent> is being downloaded.

To Reproduce

Steps to reproduce the behavior:

(Read README in repo to reproduce)

Expected behavior

When rendering a react server component server side, all its children should be also rendered server side, unless the children explicitly has use client directive.

Link to repl or repo (highly encouraged)

Repo to reproduce

sergio-milu commented 1 year ago

any update on this? I'm having same issue, also with NextJS 13.5 @gregberge

cadillaclizard commented 8 months ago

While using Next.js 14.1 dev server with --turbopack. SVGR causes:

Unhandled Runtime Error
Error: Unsupported Server Component type: {...}

There should be a config or param option that makes SVGR export components with use client directive. It's unusable in that state.

mcAnastasiou commented 8 months ago

Also having the same issue on NextJS 14.1.0. It adds the svgs in client bundle too, whereas they are server components only

lmcorreia commented 4 months ago

While using Next.js 14.1 dev server with --turbopack. SVGR causes:

Unhandled Runtime Error
Error: Unsupported Server Component type: {...}

There should be a config or param option that makes SVGR export components with use client directive. It's unusable in that state.

Hey, this might not be a solution for the issue described by the OP but it could help you or somebody else that might stumble upon this issue from a quick search. We were having the same error message but only when going for a next build. Turns out it was because the svgr loader wasn't being used at all as we had included the proper rule for turbo but (currently) turbo isn't being used for next build.

So, needing both turbo for dev and webpack for prod, our solution was to simply include both the webpack config and turbo rule in next.config.js as such:

module.exports = {
  webpack(config) {
    // Grab the existing rule that handles SVG imports
    const fileLoaderRule = config.module.rules.find((rule) =>
      rule.test?.test?.('.svg'),
    );

    config.module.rules.push(
      // Reapply the existing rule, but only for svg imports ending in ?url
      {
        ...fileLoaderRule,
        test: /\\.svg$/i,
        resourceQuery: /url/, // *.svg?url
      },
      // Convert all other *.svg imports to React components
      {
        test: /\\.svg$/i,
        issuer: fileLoaderRule.issuer,
        resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] }, // exclude if *.svg?url
        use: ['@svgr/webpack'],
      },
    );

    // Modify the file loader rule to ignore *.svg, since we have it handled now.
    fileLoaderRule.exclude = /\\.svg$/i;

    return config;
  },
  experimental: {
    turbo: {
      rules: {
        '*.svg': {
          loaders: ['@svgr/webpack'],
          as: '*.js',
        },
      },
    },
  },
};