Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SVGR fails to load SVGs with Next 11 #26130

Closed
ScottAgirs opened this issue Jun 15, 2021 · 38 comments · Fixed by #26281
Closed

SVGR fails to load SVGs with Next 11 #26130

ScottAgirs opened this issue Jun 15, 2021 · 38 comments · Fixed by #26281
Assignees
Labels
kind: bug Confirmed bug that is on the backlog

Comments

@ScottAgirs
Copy link

ScottAgirs commented Jun 15, 2021

UPDATE

A temporary solution that seems to work and does not disable Webpack 5

If you find any issues with this solution, please tag me @ScottAgirs to update as appropriate.
By @dohomi

  webpack (config) {
    const fileLoaderRule = config.module.rules.find(rule => rule.test && rule.test.test('.svg'))
    fileLoaderRule.exclude = /\.svg$/
    config.module.rules.push({
      test: /\.svg$/,
      loader: require.resolve('@svgr/webpack')
    })
    return config
  }

What version of Next.js are you using?

Next 11.0.0

What version of Node.js are you using?

14.x

What browser are you using?

Chrome, Brave

What operating system are you using?

macOS 11.4

How are you deploying your application?

localhost atm

Describe the Bug

https://discord.com/channels/752553802359505017/752668543891276009/854396809497673788

After upgrading from 10.x Next.js with webpack 4 config, to Nextjs 11, application fails to build with the below errors:

error - ./icon.svg
TypeError: unsupported file type: undefined (file: undefined)

Screen Shot 2021-06-15 at 1 12 25 PM

Full stack trace when trying to load the app (open in browser tab)

----- Expand to view -----
Error: Cannot find module '/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/.next/server/pages-manifest.json'
Require stack:
- /Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/next-server/server/require.js
- /Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/next-server/server/load-components.js
- /Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/next-server/server/api-utils.js
- /Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/next-server/server/next-server.js
- /Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/server/next.js
- /Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/server/lib/start-server.js
- /Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/cli/next-dev.js
- /Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/bin/next
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
    at Function.mod._resolveFilename (/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/build/webpack/require-hook.js:4:1855)
    at Function.Module._load (internal/modules/cjs/loader.js:725:27)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at getPagePath (/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/next-server/server/require.js:1:735)
    at requirePage (/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/next-server/server/require.js:1:1397)
    at loadComponents (/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/next-server/server/load-components.js:1:1289)
    at DevServer.findPageComponents (/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/next-server/server/next-server.js:77:296)
    at DevServer.renderErrorToHTML (/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/next-server/server/next-server.js:139:209) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/next-server/server/require.js',
    '/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/next-server/server/load-components.js',
    '/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/next-server/server/api-utils.js',
    '/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/next-server/server/next-server.js',
    '/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/server/next.js',
    '/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/server/lib/start-server.js',
    '/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/cli/next-dev.js',
    '/Users/scottagirs/workspace/iJS/ijs.to/iJStoFE/node_modules/next/dist/bin/next'
  ]
}

To Reproduce

Upgrade to Next 11 and add next.config.js

module.exports = {
  webpack(config, options) {
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    });

    return config;
  },
};

in package.json

"@svgr/webpack": "^5.5.0",
"next": "^11.0.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
@ScottAgirs ScottAgirs added the bug Issue was opened via the bug report template. label Jun 15, 2021
@ScottAgirs ScottAgirs changed the title SVGR fails to load svgs with Next 11 SVGR fails to load SVGs with Next 11 Jun 15, 2021
@sambecker
Copy link
Contributor

sambecker commented Jun 15, 2021

Getting same error message when pulling in SVGs using npm package next-images.

The following works in Next 10.2.3. but not 11.0.0 (both with Webpack 5):

import SvgImage from '../../images/image.svg';

@dreamer01
Copy link

Was using svg-url-loader, got following error

error - ./assets/images/logo.svg
TypeError: unsupported file type: undefined (file: undefined)

Tried after installing @svgr/webpack
Still facing the same issue.

@kripod
Copy link
Contributor

kripod commented Jun 15, 2021

I found a temporary workaround until an official solution is available.

Firstly, add the following to next.config.js:

module.exports = {
  images: {
    disableStaticImages: true,
  },
};

After that, fix type checking errors via patch-package:

  • Remove the following snippet from node_modules/next/types/global.d.ts:
    declare module '*.svg' {
      const content: StaticImageData
    
      export default content
    }
  • Change a line as follows in node_modules/next/dist/client/image.d.ts:
      export declare type ImageProps = Omit<JSX.IntrinsicElements['img'], 'src' | 'srcSet' | 'ref' | 'width' | 'height' | 'loading' | 'style'> & {
          loader?: ImageLoader;
          quality?: number | string;
          priority?: boolean;
          loading?: LoadingValue;
          unoptimized?: boolean;
          objectFit?: ImgElementStyle['objectFit'];
          objectPosition?: ImgElementStyle['objectPosition'];
    - } & (StringImageProps | ObjectImageProps);
    + } & StringImageProps;

Run npx patch-package next and make sure to apply the patch in every environment by installing patch-package and adding it as a postinstall script.

@FDiskas
Copy link

FDiskas commented Jun 15, 2021

I would like add some reproducible demos here. p.s. Icon component is just converted to js from typescript - do not blame.
example with next10
https://stackblitz.com/edit/nextjs-8hivbq
example with next11
https://stackblitz.com/edit/nextjs-laqdgv

@ilchoTaleski
Copy link

I have the same issue. When I add webpack5: false in next.config.js it works. I am using next-images without any loader configuration.

@mxmtsk
Copy link

mxmtsk commented Jun 15, 2021

This seems to be a duplicate of #25950.

@chozzz
Copy link
Contributor

chozzz commented Jun 16, 2021

This might also be related as it also happens to me, but non svgr related.
However, this happens after upgrading from 10.1.3 to 11.0.0.

./public/static/images/about/faq-cod-visibility.png
TypeError: unsupported file type: undefined (file: undefined)

> Build error occurred
Error: > Build failed because of webpack errors
    at /home/choz/dev/projects/fe/node_modules/next/dist/build/index.js:15:924
    at async Span.traceAsyncFn (/home/choz/dev/projects/fe/node_modules/next/dist/telemetry/trace/trace.js:6:584)

Setting webpack5: false does fix the issue for me too.

@kylemh
Copy link
Contributor

kylemh commented Jun 16, 2021

I added a feature request to internalize SVGR into Next.js's core webpack configuration. Please voice your support there!

#26157

@jakeherp
Copy link

I flagged this issue yesterday in Discord (see https://discordapp.com/channels/752553802359505017/752647196419031042/854484227047555102), the proposed solution by @styfle was to use disableStaticImages: true, but this means losing support for some of the amazing new features for next/images.
The other proposed solution was to import SVGs as fs.readFile('./file.svg') and then setting them using dangerouslySetInnerHTML, but I don't think this is a viable solution as firstly the readFile needs to happen serverside and secondly it adds unnecessary complexity.

I believe that inline SVGs are a very common use case and this should be patched in a minor version release soon. One option could be to exclude SVGs from static imports, when svgr/webpack is set up in next.config.js

@mohux
Copy link

mohux commented Jun 16, 2021

It will have to be fixed in a minor version, no worries they will surely fix it, just give them time to relax after preparing for the huge confrencee
if you are in deep need for SVG, there are multiple solutions for now (not optimal)

1 - change svg to react components and extend React.HTMLAttrbitutes<HTMLSVGElement> and pass props to svg
2 - disable webpack5 but you will lose a lot of benifits like and probably static files wont work (blurry image placeholder for example)

3- disable staticImages images: { disableStaticImages: true, },

4 - import svg as images not as components

@njmh
Copy link

njmh commented Jun 16, 2021

I'm facing this issue too sadly. I make heavy use of both next/image and inline SVGs (using SVGR) in most of my Next projects so the workarounds propsed aren't adequate. Curious why SVG was added to static image type definitions when the use cases for inlining SVGs are so common?

@bastiankistner
Copy link

bastiankistner commented Jun 16, 2021

I thought a lot about this change. First I was frustrated, then I reflected on how I am using SVGs. I've also been utilising SVGR to inline my SVGs. But only to be able to re-color and modify a few SVG attributes.

It actually makes sense to me not to inline SVGs if these are my requirements. But so far I had not thought about a different approach. Asking Google, it turned out it'd be an option to leverage the <use/> tag in combination with the src attribute that comes with StaticImageData. However, this requires all SVGs to have a unique id as in the following snippet:

// MySvg.svg
<svg id="root" ... />

// then use it later when imported through `next-image-loader`
import {src} from './MySvg.svg'

<svg>
   <use href={`${src}#root`} />
</svg>

That was not the case for my assets.

Therefore I experimented with a few webpack loaders. I tried svg-as-symbol-loader and string-replace-loader. The former had to be modified, the latter only allowed a simple string replacement, which can easily fail or be insufficient.

However, the experiment turned out to solve my issue AND my SVGs can now be cached properly while still being able to use my SVG attributes as before. I also don't have to use an img tag, which I see as a less flexible alternative as we cannot style the svg any longer.

I went a step further and created a custom loader that is a bit smarter than those I tried before. You can find it here together with some docs that further describe its usage and implementation:

https://www.npmjs.com/package/svgid-loader

All it does is to add an id attribute to the first svg element it finds. Take a look at the sources here and leave your feedback.

Might not be a solution for everyone, but I actually will stick with it from now on as it also reduces markup, enables caching and complies with how nextjs loads such assets.

@mohux
Copy link

mohux commented Jun 16, 2021

I thought a lot about this change. First I was frustrated, then I reflected on how I am using SVGs. I've also been utilising SVGR to inline my SVGs. But only to be able to re-color and modify a few SVG attributes.

It actually makes sense to me not to inline SVGs if these are my requirements. But so far I had not thought about a different approach. Asking Google, it turned out it'd be an option to leverage the <use/> tag in combination with the src attribute that comes with StaticImageData. However, this requires all SVGs to have a unique id as in the following snippet:

// MySvg.svg
<svg id="root" ... />

// then use it later when imported through `next-image-loader`
import {src} from './MySvg.svg'

<svg>
   <use href={`${src}#root`} />
</svg>

That was not the case for my assets.

Therefore I experimented with a few webpack loaders. I tried svg-as-symbol-loader and string-replace-loader. The former had to be modified, the latter only allowed a simple string replacement, which can easily fail or be insufficient.

However, the experiment turned out to solve my issue AND my SVGs can now be cached properly while still being able to use my SVG attributes as before. I also don't have to use an img tag, which I see as a less flexible alternative as we cannot style the svg any longer.

I went a step further and created a custom loader that is a bit smarter than those I tried before. You can find it here together with some docs that further describe its usage and implementation:

https://www.npmjs.com/package/svgid-loader

All it does is to add an id attribute to the first svg element it finds. Take a look at the sources here and leave your feedback.

Might not be a solution for everyone, but I actually will stick with it from now on as it also reduces markup, enables caching and complies with how nextjs loads such assets.

it actually makes since since svg adds more elements to HTML page which increase number of max child elements and total elements, that's not good for lighthouse

but still some people already got hundreds of inline svgs added and will likely take lot of time to change

@jakeherp
Copy link

jakeherp commented Jun 16, 2021

I would argue, that an inline SVG almost always has benefits for your performance and therefore the lighthouse score over additional requests by loading them from an external file.
If you get to the point that the number of child elements of your DOM becomes an issue you have other problems to look at first 😉.

Exceptions for this rule are complex SVGs, which should probably be imported as an image or even be stored in a more efficient format (such as webp / png).

@bastiankistner
Copy link

bastiankistner commented Jun 16, 2021

I have just migrated my codebase, didn't take too long actually and it works even better than I thought. I'm using the svgid-loader and have a custom Svg component (see below).

All I needed to do was replace my former Svg wrapper with this component and make sure the image data prop is being parsed as in <Svg style={{ width: 40, height: 'auto' }} data={ImageSvg} />.

@jakeherp I think it depends very much on your use-case. Why would I inline an SVG? The only option (besides not yet benchmarked performance aspects) I can think of is when I'd like to modify the paths e.g. because I want to animate something. And here it's perfectly fine to just copy and paste the svg markup into a real component file.

If I can still apply all attributes and have SVGO as an additional loader, I don't see the need for something like SVGR.
I'd even assume that with using proper external SVG files, I can benefit from having those assets served with a cacheable hashed URL that would only change when the content of the SVG changes. Whereas the likeliness that my component or related code changes seems much higher and would result in having the user re-download the component including the SVG markup. And we can further leverage a service worker to cache those SVG requests if it makes sense.

Svg component I am using:

interface StaticImageData {
	src: string;
	height: number;
	width: number;
	placeholder?: string;
}

export const Svg = ({
	data: { width, height, src },
	style,
	...rest
}: { data: StaticImageData } & React.SVGProps<SVGSVGElement>) => {

	const enhancedStyle = { ...style };

	if (typeof enhancedStyle.width !== 'undefined' && typeof enhancedStyle.height === 'undefined') {
		enhancedStyle.height = 'auto';
	}

	if (typeof enhancedStyle.height !== 'undefined' && typeof enhancedStyle.width === 'undefined') {
		enhancedStyle.width = 'auto';
	}

	return (
		<svg viewBox={`0 0 ${width} ${height}`} style={enhancedStyle} {...rest}>
			<use href={`${src}#root`} />
		</svg>
	);
};

Combined with SVGO in my nextjs.config.js

config.module.rules.push({
    test: /\.svg$/i,
    use: [{
            loader: 'svgid-loader',
            options: {
                id: 'root',
                overwrite: true,
            },
        },
        {
            loader: 'svgo-loader',
            options: {
                multipass: true,
                plugins: require('svgo').extendDefaultPlugins([('convertStyleToAttrs', 'removeStyleElement')]),
            },
        },
    ],
});

@kylemh
Copy link
Contributor

kylemh commented Jun 16, 2021

Is svgo running? Just curious to know if custom webpack rules run before or after static image loaders within next core.

@bastiankistner
Copy link

When I tested it the order mattered. Using config.module.rules.push in my example first applies the svgo-loader, then the svgid-loader and afterwards the next-image-loader that is set for all image assets by nextjs. So yes, it works well. I'm stripping styles and convert them to inline. Otherwise some styles seem to not be applied. And using the extendDefaultPlugins should cover what SVGR comes out of the box with.

@dohomi
Copy link

dohomi commented Jun 17, 2021

You can try this solution which does not disable static images:
#25950 (comment)

@kevinseabourne
Copy link

kevinseabourne commented Jun 17, 2021

Sweet it worked with url-loader. Without having to disable static images 🤘

webpack: (config) => {
    const fileLoaderRule = config.module.rules.find(
      (rule) => rule.test && rule.test.test(".svg")
    );
    fileLoaderRule.exclude = /\.svg$/;
    
    config.module.rules.push(
      {
        test: /\.(png|jpg|gif|woff|woff2|otf|ttf|svg)$/i,
        use: [
          {
            loader: "url-loader",
            options: {
              limit: 100000,
            },
          },
        ],
      },
      {
        test: /\.(png|jpe?g|gif|mp3|aif)$/i,
        use: [
          {
            loader: "file-loader",
            options: {
              name: "static/media/[name].[hash:8].[ext]",
            },
          },
        ],
      }
    );

    return config;
  }

@ScottAgirs
Copy link
Author

ScottAgirs commented Jun 17, 2021

For anyone still looking for a solution, to add to what @dohomi suggested in #26130 (comment) - in case u're using SVGO or need to configure any other options, this should work just fine:

next.config.js

webpack(config, options) {
    const fileLoaderRule = config.module.rules.find(rule => rule.test && rule.test.test('.svg'))
    fileLoaderRule.exclude = /\.svg$/

    config.module.rules.push({
      loader: '@svgr/webpack',
      options: {
        prettier: false,
        svgo: true,
        svgoConfig: {
          plugins: [{ removeViewBox: false }],
        },
        titleProp: true,
      },
      test: /\.svg$/,
    });

    return config;
}

@arcataroger
Copy link

I would argue, that an inline SVG almost always has benefits for your performance and therefore the lighthouse score over additional requests by loading them from an external file.
If you get to the point that the number of child elements of your DOM becomes an issue you have other problems to look at first 😉.

Exceptions for this rule are complex SVGs, which should probably be imported as an image or even be stored in a more efficient format (such as webp / png).

Are you sure about this? Are there benchmarks? I wonder about potential downsides, like:

  • If you re-use an SVG component several times in the same page, is it getting rendered to HTML and in-lined multiple times? A 1kB icon used 20x on a page would then become a 20kB icon
  • The inlined HTML can't be cached by your browser for when it's used again on another page... so something like your logo or a search bar icon has to be redownloaded on every page
  • It can't be lazy-loaded if it's all just part of the HTML, and this slows down your actual content since it's all just one stream instead of being separate network resources that can be fetched later (or prefetched between pages)
  • You lose out on the ability to use alt tags and have to use an alternative title tag for screen readers

If you don't need to be able to dynamically/programmatically restyle the SVG, I don't know that the tiny savings from fewer network requests outweighs the potential cons... but I'd love to be proven wrong if I am.

@styfle styfle added kind: bug Confirmed bug that is on the backlog and removed bug Issue was opened via the bug report template. labels Jun 17, 2021
@styfle styfle self-assigned this Jun 17, 2021
@jakeherp
Copy link

@arcataroger you've got some valid points, I see an inline SVG just like any other component, it's markup that obviously has a size to it, but if an SVG gets to a size of 1kb or more I'd definitely not use it as an inline element anymore.
The use case for inline SVGs (at least in my case) is for simple icons (the kind we would have used an icon font for a few years ago) - for example, a Github icon has around 350 bytes, so even if I was importing this 10 times, it'd not be a concern.

Accessibility is not really an issue either, as I can give a title to the link or button that contains the SVG, or if you really want to do this within the SVG, you can pass a <title> tag inside the SVG.

This is becoming a bit off-topic and I know that this is a very particular use case, but it is yet a very common one.

@arcataroger
Copy link

@jakeherp Makes sense, and you're right that it's a bit offtopic... my bad!

@styfle
Copy link
Member

styfle commented Jun 17, 2021

Thanks for reporting this issue!

A large percentage of Next.js user are relying on @svgr/webpack and similar alternatives so we'll get this fixed!

See PR #26281

@kodiakhq kodiakhq bot closed this as completed in #26281 Jun 18, 2021
kodiakhq bot pushed a commit that referenced this issue Jun 18, 2021
This PR does a couple things:

1. Omit svg static imports if the user has defined custom webpack config with svg rule
2. Change TS type to `any` for svg imports to avoid conflicts with other plugins

The idea is that some users want to use `next/image` with static imports for most image types but not for svg and instead inline those images with a plugin.

- Fixes #25950  
- Fixes #26130 
- Fixes #26176 
- Fixes #26196 
- Fixes #26067 


## Bug

- [x] Related issues linked using Fixes #26130 
- [x] Integration tests added
@styfle
Copy link
Member

styfle commented Jun 18, 2021

The fix is available in next@11.0.1-canary.4

You can try it out today with yarn add next@canary. Thanks!

flybayer pushed a commit to blitz-js/next.js that referenced this issue Jun 24, 2021
…6281)

This PR does a couple things:

1. Omit svg static imports if the user has defined custom webpack config with svg rule
2. Change TS type to `any` for svg imports to avoid conflicts with other plugins

The idea is that some users want to use `next/image` with static imports for most image types but not for svg and instead inline those images with a plugin.

- Fixes vercel#25950  
- Fixes vercel#26130 
- Fixes vercel#26176 
- Fixes vercel#26196 
- Fixes vercel#26067 


## Bug

- [x] Related issues linked using Fixes vercel#26130 
- [x] Integration tests added
@Pipe-Runner
Copy link

For anyone still looking for a solution, to add to what @dohomi suggested in #26130 (comment) - in case u're using SVGO or need to configure any other options, this should work just fine:

next.config.js

webpack(config, options) {
    const fileLoaderRule = config.module.rules.find(rule => rule.test && rule.test.test('.svg'))
    fileLoaderRule.exclude = /\.svg$/

    config.module.rules.push({
      loader: '@svgr/webpack',
      options: {
        prettier: false,
        svgo: true,
        svgoConfig: {
          plugins: [{ removeViewBox: false }],
        },
        titleProp: true,
      },
      test: /\.svg$/,
    });

    return config;
}

Thanks a lot; this worked for me.

@schoenwaldnils
Copy link
Contributor

Just updated to next@11.0.1
There you don't need the fileLoaderRule.exclude anymore.
In fact it breaks the build.

@Pipe-Runner
Copy link

Pipe-Runner commented Jul 9, 2021

For anyone struggling with this issue, this worked for me. Next v11 and webpack5
https://stackoverflow.com/a/67641345/8895077

@Klohto
Copy link

Klohto commented Aug 10, 2021

I'm not entirely sure if #26281 and #26548 solve anything.

You test specifically for rule.test.test('.svg')

rule.test.test('.svg')

but most people running SVGR and next.js have more complicated regexes than just /.svg$/.
For them, this fix doesn't do much.

On top of that, you can now either use SVG in SVGR or in next/image, not both. At least not by default.

Consider our case. We filter all SVGs that match /\.react\.svg/ pattern (discord.react.svg would match, while checkbox.svg would not). Clearly, my regex pattern would not go through the current fix's checks so the build fails on unsupported file type: undefined because I cannot mix SVG in both next.js and SVGR.

The workaround is to use this ugly config that includes the regex pattern for SVGR while excluding it in the next-image-loader (commented out part doesn't work for some reason):

  webpack(config) {
    
   config.module.rules.push({
     test: /\.react\.svg$/,
     use: ["@svgr/webpack"]
   });

  //  config.module.rules.push({
  //    test: /\.(png|jpg|jpeg|gif|webp|ico|bmp|.svg)$/i,
  //    exclude: [
  //      /\.react\.svg$/,
  //    ],
  //    use: ["next-image-loader"]
  //  });

   const imageLoaderRule = config.module.rules.find(rule => rule.loader == "next-image-loader")
   imageLoaderRule.exclude = /\.react\.svg$/

   return config;
  }
 }

"Just use this config then" - Well, it's incredibly ugly, requires maintenance from the user and if next.js is already trying to be smart, I don't see why should I.
Considering the logic is already there, can't you just test if the non-next-image-loader RegExp contains .svg pattern (eg. .svg in react.svg) and exclude the whole previous regex pattern in next-image-loader (as what I tried to do with exclude)?

Because right now if you search for SVGR and next.js compatibility, you'll find that it has been fixed. You test, realize the build is still not working and spend 4 hours tracking down the issues only to start reading the source code anyway. In the end, you realize the official support is minor and works on this specific issue that does not cover your use-case at all.

I don't see a problem with the fix itself, but it would be nice if it would either support most (if not all) use-cases. It's almost there already.

@Vsion
Copy link

Vsion commented Sep 17, 2021

The fix is available in next@11.0.1-canary.4

You can try it out today with yarn add next@canary. Thanks!

It still doesn't take effect for me

@FDiskas
Copy link

FDiskas commented Sep 17, 2021

Latest stable nextjs works in my case

@Vsion
Copy link

Vsion commented Sep 17, 2021

Latest stable nextjs works in my case

how dose your config look like

@FDiskas
Copy link

FDiskas commented Sep 17, 2021

…
webpack(config, options) {
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack', 'url-loader'],
    });

    return config;
},

@Vsion
Copy link

Vsion commented Sep 17, 2021

image

TestSvg in next v9 is a react element

still doesnot work in my project after upgrade next 11

@Vsion
Copy link

Vsion commented Sep 17, 2021

my configs
`const withPlugins = require("next-compose-plugins")
const withLess = require('next-with-less')
withLess.patchNext(require("next/dist/build/webpack/config/blocks/css"));
const withAntdLess = require('next-plugin-antd-less')
const withTM = require('next-transpile-modules')
const modifyVars = require('./public/utils/theme')
const path = require('path')

const pluginAntdLess = withAntdLess({
lessVarsFilePath: './public/utils/theme.less',
modifyVars,
});

const pluginWithLess = withLess({
lessLoaderOptions: {
lessOptions: {
javascriptEnabled: true,
modifyVars,
}
},
});

module.exports = withPlugins([withTM, pluginWithLess, pluginAntdLess], {
webpack(config, options) {
config.module.rules.push({
test: /.svg$/,
use: ['@svgr/webpack', 'url-loader'],
});
return config
}
})
`

@FDiskas
Copy link

FDiskas commented Sep 17, 2021

It is probably different problem. I'm loading icons not as components. I do not render them in nextjs - i load them in client side

import * as React from 'react';

import styles from './iconComponent.module.scss';
enum Icons {
    drag = 'drag',
    minus = 'minus',
    plus = 'plus',
    comments = 'comment',
   // ...
}

interface ComponentProps {
    name: keyof typeof Icons;
}

export const IconComponent: React.FC<ComponentProps & React.SVGProps<SVGSVGElement>> = ({ name, ...rest }) => {
    const ImportedIconRef = React.useRef<React.FC<React.SVGProps<SVGSVGElement>>>();
    const [loading, setLoading] = React.useState(true);

    const importIcon = React.useCallback(async () => {
        try {
            ImportedIconRef.current = (await import(`./icons/${Icons[name]}.svg`)).ReactComponent;
        } finally {
            setLoading(false);
        }
    }, [name]);

    React.useEffect(() => {
        setLoading(true);

        importIcon();

        return () => {
            setLoading(false);
        };
    }, [importIcon, name]);

    if (!loading && ImportedIconRef.current) {
        const { current: ImportedIcon } = ImportedIconRef;

        return <ImportedIcon className={styles.root} {...rest} />;
    }

    return null;
};

IconComponent.displayName = 'IconComponent';

What I would try it would be like...

import { ReactComponent as MyIcon } from './icons/my-icon.svg';

@Barik85
Copy link

Barik85 commented Dec 14, 2021

Here is my next.config.js for fixing this problem for next@12.0.7:

const withSvgr = require('next-plugin-svgr');

module.exports = withSvgr({
  sassOptions: {
    prependData: `
      @import "~/styles/colors.scss";
      @import "~/styles/_breakpoints.scss";
      @import "~/styles/_mixins.scss";
      @import "~/styles/_fonts.scss";
    `
  }
})

@balazsorban44
Copy link
Member

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@vercel vercel locked as resolved and limited conversation to collaborators Jan 27, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
kind: bug Confirmed bug that is on the backlog
Projects
None yet
Development

Successfully merging a pull request may close this issue.