6 ms·
Breaking Up with SVG-in-JS in 2023
- davnicwil 3y agoWhile I agree it should be only used where absolutely necessary, another not insignificant benefit to 'inlining' svgs in jsx is that they're then visible immediately on first render, there's no loading time. This is particularly relevant for icons and buttons in key places in the UI, where it's janky to have them appear even a split second after the rest of the UI. How can you acheive that using other approaches?
- akdor1154 3y agoBy not using jsx? It would be an order of magnitude less waste to just set innerhtml in such a case, than to waste your users' cpu cycles diffing and reconstituting a giant tree of vdom.
- davnicwil 3y agoI'd also generalise the question beyond jsx to just 'inline with javascript' - ie just as you say, inject the svg markup into the DOM synchronously using the same javascript that renders the DOM (rather than some deferred source) - it's just most of the time for me that means jsx.
- montroser 3y agoJust include an SVG sprite in the HTML page. Then, like the article says, you can reference each icon with <use href="#icon-name" /> and they will be available far before your js bundle is parsed.
- afavour 3y agoYou could also just use data URIs in your CSS. “How else could you possibly have SVGs render inline other than to include a massively bloated JS representation of a string in your bundle?” - the React ecosystem, 2023 The answer, as you’ve shown, is “use the platform”. Sometimes I feel like React actively works against that.
- davnicwil 3y ago[Edited per below comment pointing out my mistake about external CSS loading order] -- this is a decent alternative, thanks!
- jacobr 3y agoExternal css files are render blocking, meaning any content after a <link rel=stylesheet> will not be visible until the css has been loaded.
- deleted 3y ago[deleted]
- bryanrasmussen 3y agoI have this idea that as you go up a level of stack parts of the underlying stack get underused, people want to use things at the same level in the stack - for example if you are using React or Vue have everything React or Vue. This makes things work worse because of course you have those underlying levels for a reason, but it makes people feel architecturally purer or something (it is at this point the idea breaks down for me, I have no idea why it is that everything should be in whatever framework you are using, just that this seems to how everyone I ever work with feels on the matter)
- afavour 3y agoI agree, I also think React is a particularly regular victim because of JSX. A JSXed SVG looks just the same as a regular SVG in your editor, if everyone was forced to see the endless chains of React.createElement() they might start to feel uneasy.
- butz 3y agoUsing SVG sprites gives benefit of caching, as icons tend to change less frequently than main application code. And be very careful to use real SVG, not bitmaps wrapped in SVG, as it will very quickly bloat your sprite size.
- deleted 3y ago[deleted]
- c_s_guy 3y agoAre there any negative impacts to accessibility with the `<use href="#icon-name" />` sprite approach?
- dreamcompiler 3y agoThis sounds to me like "You should generate images one pixel at a time from javascript, because they will render immediately. Never use those obsolete <img> tags."
- andreidd 3y agoUsing the svg as mask image in css is presented to have the disadvantage of two separate requests (one for css and the other for the svg content). That can be overcome by inlining the svg directly in the css file.
- Aeolun 3y agoIs this another ‘optimize away this extra 5ms step on the worst phone in existence’ article? I need some rough numbers before I’ll pay any attention to something like this.
- awestroke 3y agoYeah there is a suspicious lack of performance numbers in the article
- afavour 3y agoI don’t think there’s anything wrong in pointing out that X is a better practise than Y, even if only by a small amount. As the tweet in the article points out, it’s really easy to multiply that tiny benefit by 1000 icons before you know what you’re doing. Why not start off on the best foot? I don’t want to sound too negative (but I’m about to): this attitude in web development really bugs me. Shaving 5ms off render time on a crappy Android device should be a desirable goal, not something you have to be cajoled into doing. You should be motivated by that! But instead the industry is all about “DX”: is that change going to complicate my precious build script? Then out the window it goes. We have an industry that prioritises developer experience over user experience and I think that has a role to play in the shittiness of the web these days.
- Aeolun 3y agoThat’s not really my point. All of these icons will cost you 5ms at worst. Should we make that tradeoff in the first place? The article present this as something you must do, or else you don’t care about your users. But as someone else points out elsewhere, including the icons in your code means no lazy loading, so everything is either instantly there or not at all. That’s a much bigger user benefit than a minimally faster bundle load. I just don’t see a convincing (concrete) argument in this article.
- afavour 3y ago> But as someone else points out elsewhere, including the icons in your code means no lazy loading And if you check the replies you’ll see examples of other, more efficient ways to do the exact same thing. It speaks to a bad level of myopia in the React community that when presented with the challenge of “put statically rendered markup in HTML” the accepted solution is “take that markup, transform it into a bloated JS representation, transform it back to markup during server side render while also shipping the bloated representation in the client JS, then unnecessarily hydrate that representation on page load” and no one sees any problem.
- skrebbel 3y agoThe inline-in-html trick looks very nice indeed! We have a low-ish amount of different svg icons (as JSX) used in many places (potentially 1000s). This should help reduce the DOM size quite significantly at no downside (that I can see). Thanks!
- earthboundkid 3y agoI think the long and short of it is if you need performance, don’t use an SPA. Anything you do in a JS bundle for an SPA is going to be more expensive than just doing a normal HTML page. And that’s fine! But don’t be confused about what you’re trading off against.
- mickael-kerjean 3y ago> if you need performance, don’t use an SPA you can make a SPA using vanilla JS, without any bundle using plain es6 module and be perfectly fine. I made one such scaffold to showcase people how to do exactly that: https://mickael-kerjean.github.io/skeleton/example/index.html https://mickael-kerjean.github.io/skeleton/example/index.htm...
- earthboundkid 3y agoOkay, but it will be slower to first render than a normal HTML page because you have to download the HTML plus execute the JS vs just download the HTML. Again, that’s fine, but it’s an inescapable part of the trade off.
- mickael-kerjean 3y agoDoesn't have to be, it's not very popular these days but we used to talked about progressive enhancement, the idea being you should prerender your thing in HTML and spice it up with JS, this is also covered in the POC and is unfortunatly something that got lost over time in favor of "modern framework" and the new meta everything fad
- earthboundkid 3y agoProgressive enhancement is, by definition, not a SPA.
- deleted 3y ago[deleted]
- thriftwy 3y agoIf people are doing that a lot, why not optimize browsers to handle this better?
- beebeepka 3y agoI don't think browsers should optimise for whatever the react cult happens to like this year because, as history has shown, they preach one thing now, then change their opinion months or years later
- tomxor 3y ago> SVGs in JS have a cost and SVGs do not belong into your JS bundle This article appears to do a reasonable job of weighing the the performance pros and cons to justify such a broad statement. However it fails to consider the use cases beyond plonking static SVG images into a page. The initial example of "people are embedding SVG icon packages as SVG in JS" seems to be the only type of use case that each abstract justification is being validated in. This advice needs a heavy qualifier of "for static assets", and even then, only when dealing with large individual assets, or large quantities of individual and artificially inseparable SVGs such as icon packages. I'm suspicious this whole argument stems from people blindly "importing" svg bundles into JS without fully understanding what that actually means in the end result of their bundle. It would be more useful to talk about this issue with it's original context, where there are multiple lessons to learn than coerce it into an over generalisation.
- deleted 3y ago[deleted]
- joduplessis 3y agoCSS-in-JS is a far more pervasive issue IMO. SVG-in-JS has a definite performance cost, but it's not an anti-pattern.
- willio58 3y agoWe do this at my job. Do you have any good articles that describe clearly why this is bad? On the surface I assume it’s because you need to load all the js, create the dom, and then apply css in that order instead of just having a separate file for css loaded quickly at the beginning and letting the dom load in after. But is there a benefit to css in js where only the css used in the components your rendering is loaded? Like an automatic code splitting for css?
- ttfkam 3y agoNo mention of fragment identifiers and the <view> tag for SVG sprites? Simplifies the markup quite a bit. https://developer.mozilla.org/en-US/docs/Web/SVG/Element/view https://developer.mozilla.org/en-US/docs/Web/SVG/Element/vie...