-
Notifications
You must be signed in to change notification settings - Fork 27k
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
Comments
Getting same error message when pulling in SVGs using npm package The following works in Next
|
Was using
Tried after installing |
I found a temporary workaround until an official solution is available. Firstly, add the following to module.exports = {
images: {
disableStaticImages: true,
},
}; After that, fix type checking errors via
Run |
I would like add some reproducible demos here. p.s. Icon component is just converted to js from typescript - do not blame. |
I have the same issue. When I add |
This seems to be a duplicate of #25950. |
This might also be related as it also happens to me, but non svgr related.
Setting |
I added a feature request to internalize SVGR into Next.js's core webpack configuration. Please voice your support there! |
I flagged this issue yesterday in Discord (see https://discordapp.com/channels/752553802359505017/752647196419031042/854484227047555102), the proposed solution by @styfle was to use 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 |
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 1 - change svg to react components and extend 3- disable staticImages 4 - import svg as images not as components |
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? |
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 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 // 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 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 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 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 |
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. 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). |
I have just migrated my codebase, didn't take too long actually and it works even better than I thought. I'm using the All I needed to do was replace my former Svg wrapper with this component and make sure the image @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. 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 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')]),
},
},
],
}); |
Is |
When I tested it the order mattered. Using |
You can try this solution which does not disable static images: |
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;
} |
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:
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;
} |
Are you sure about this? Are there benchmarks? I wonder about potential downsides, like:
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. |
@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. 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 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. |
@jakeherp Makes sense, and you're right that it's a bit offtopic... my bad! |
Thanks for reporting this issue! A large percentage of Next.js user are relying on See PR #26281 |
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
The fix is available in You can try it out today with |
…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
Thanks a lot; this worked for me. |
Just updated to next@11.0.1 |
For anyone struggling with this issue, this worked for me. Next v11 and webpack5 |
I'm not entirely sure if #26281 and #26548 solve anything. You test specifically for next.js/packages/next/build/webpack-config.ts Line 1563 in 8cbaa40
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 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):
"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. 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. |
It still doesn't take effect for me |
Latest stable nextjs works in my case |
how dose your config look like |
|
my configs const pluginAntdLess = withAntdLess({ const pluginWithLess = withLess({ module.exports = withPlugins([withTM, pluginWithLess, pluginAntdLess], { |
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'; |
Here is my
|
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. |
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
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:
Full stack trace when trying to load the app (open in browser tab)
----- Expand to view -----
To Reproduce
Upgrade to Next 11 and add
next.config.js
in
package.json
The text was updated successfully, but these errors were encountered: