[HN Gopher] We improved React loading times with Next.js
___________________________________________________________________
We improved React loading times with Next.js
Author : Lukas1994
Score : 62 points
Date : 2022-10-24 13:01 UTC (10 hours ago)
(HTM) web link (www.causal.app)
(TXT) w3m dump (www.causal.app)
| gatvol wrote:
| Ssr to improve a static app performance? Sounds like madness to
| me. More complexity plus much larger surface to secure.
| adchurch wrote:
| One nice thing about Next.js is you don't need to use SSR
| unless absolutely necessary - it will statically generate all
| your pages by default (which is similar to but not the same as
| SSR - it runs once at build time rather than on every single
| request), so the result is similar to CRA but with quicker
| first page load times and a much better developer experience.
|
| But you have the power to use SSR where necessary too, which is
| not really possible with CRA (without unscalable hacks).
| joshuakgoldberg wrote:
| I'm so excited about this . It's a testament to how well-built-up
| modern frontend tooling is, especially around React. The things
| that used to take hundreds or even thousands of lines of config
| can now be done in a few dozen at most with managed libraries.
| And better!
| maigret wrote:
| Unfortunately too much JS has made the web slower, check this
| https://www.speedcurve.com/blog/web-performance-page-bloat/ for
| a quick view or infrequently.org for longer explanations. React
| starts to be dated now and there are leaner alternatives
| offering most of the functional advantages, like Svelte or Lit.
|
| The tooling evolves indeed and I hope it gets again nearer to
| the browsers, thanks to web components, better CSS (hello
| variables), WASM and much more.
| subpixel wrote:
| I've been checked-out of the SSG world for a couple years and am
| now evaluating different tools and frameworks for a project at
| work.
|
| I'm intrigued by the direction being taken by Remix, which posits
| that today's backend options are so improved compared to those of
| the recent past that they (arguably) have eroded the utility of a
| static site, period.
|
| https://remix.run/blog/remix-vs-next
|
| When it's not crazy difficult or expensive to have a very fast
| app _and_ database close to your users, you don't have to
| architect around that deficiency, which is what SSGs are designed
| to do.
| crooked-v wrote:
| Though it's worth keeping in mind that Next's next big
| structural update [1] is pretty much an attempt to assimilate
| some of the basic concepts of Remix wholesale.
|
| [1]: https://nextjs.org/blog/layouts-rfc
| leerob wrote:
| Not exactly - this has been in discussion for many years.
| From the post:
|
| > Some routing conventions were inspired by the Relay-based
| router at Meta, where some features of Server Components were
| originally developed, as well as client-side routers like
| React Router and Ember.js. The layout.js file convention was
| inspired by the work done in SvelteKit.
|
| No doubt React Router has certainly impacted the entire React
| ecosystem, though!
| pitnikola wrote:
| Great stuff -- thanks for the write-up! Do you mind sharing the
| Dockerfile you use for deploying?
| adchurch wrote:
| Sure! Here it is:
| https://gist.github.com/a-churchill/9a55fffaae97b347de5885e7...
| Lukas1994 wrote:
| If possible definitely use Vercel :)
| pferdone wrote:
| I mean good for them for improving their user's experience. I am
| just surprised that maintaining your own webpack config seems
| like such challenge. Enabling chunks to split code to improve
| loading times or dynamic imports, it's not exactly rocket
| science. Yes DX and all improved as well, but CRA is such a bad
| choice for production code. It gets you going fast(er), but as
| soon as you have to tweak it, it seems like devs jump to the
| "next" framework that already has those tweaks builtin...until
| they hit the next roadblock. Thus you never learn what actually
| makes it all work.
| adchurch wrote:
| Imo it's a question of prioritization - time spent fiddling
| with a Webpack config is time that could have been spent on
| something that will more immediately benefit a user. That's the
| big advantage we saw for switching to Next.js, which handles
| this and many other details for us, _without_ the confusing &
| brittle hacks that had accumulated in our CRA setup.
|
| > Thus you never learn what actually makes it all work.
|
| I agree this is unsatisfying - however it's a problem no matter
| what! We have to live at some level of abstraction in order to
| make any forward progress. There can still be lots of learning
| along the way!
| throwaway4good wrote:
| What does next.js offer if server side rendering is of no
| relevance? It seems to me that ssr adds a lot of complexity and a
| great number of projects have no need for it at all.
| gherkinnn wrote:
| It takes care of all the boring stuff like reliable reloads,
| .env files, routing, config (without me writing any), bundling,
| etc. It leaves me the fuck alone.
|
| SSR doesn't add too much complexity and at the very least is a
| reliable way to serve a server-rendered shell of the
| application so the content doesn't fly about as it loads.
| jonny_eh wrote:
| I also like how it adds a light API layer, you can proxy 3rd-
| party APIs to your front-end.
| yunohn wrote:
| This is a huge advantage when you're building client-side
| apps that need a light backend.
| hklgny wrote:
| 100% this. Spinning up a new Next project "just works" for
| getting started, and makes me confident in a scaling path as
| times goes on. Adding things like lightweight API routes
| (weirdly useful in a ton of situations) or pulling in
| interactivity are trivial.
|
| I still write static HTML if I'm positive it'll be a forever
| fit - but anything client facing or with an ambiguous feature
| I reach for Next.
| Scarbutt wrote:
| nextjs is crap but IMO doing react ssr on most requests with
| hydration is faster, more robust and less complex than going
| full csr/spa.
| lewisl9029 wrote:
| Curious to hear from people out there using Next.js, but
| without _any_ SSR, i.e. using the `next export` command
| mentioned in the article: https://nextjs.org/docs/advanced-
| features/static-html-export
|
| (Seems like the folks in the article are beginning to use SSR,
| and have some great use cases with publicly available, SEO-
| friendly content, but a lot of apps don't, and can benefit from
| avoiding the operational complexity.)
|
| Create React App is a bit long in the tooth these days, so I
| can imagine `next export` being a lot nicer to work with in a
| whole bunch of ways, but the only advantage of `next export` I
| can think of over something more modern like Vite is file-
| system routing.
|
| For those using `next export` but have also evaluated Vite, is
| FS routing what made you choose `next export`? Or is it
| something else?
|
| Disclaimer: Asking with ulterior motives. I'm building
| https://reflame.app, a Vercel competitor focused on client-
| rendered React apps, with millisecond deploy times to previews
| and production. We currently have decent compatibility with
| Vite and CRA, but considering if we should try to add support
| for apps using `next export` as well.
| hultner wrote:
| I've used the next export based approach on quite a few
| projects and agree with previous commenters, next takes care
| of a lot of the boring stuff when setting up a new project
| and the routing feels refreshingly out of the way compared to
| many pre-next alternatives.
| pen2l wrote:
| The obvious argument, tried and cliche as it may sound, would
| be that SPA are anti-web. A healthy web must be indexable and
| searchable. It almost seems like the rulebook now for some
| newcomers is to start out with SSR, make use of the auspices of
| the open web that allow for easy and organic discovery, - and
| after a significant marketshare has been captured, erecting all
| types of of lock-in walls, including turning SPA.
| endisneigh wrote:
| SPAs can be indexed, so the entire premise of your post is
| invalid.
| ipaddr wrote:
| Not sure you understand what indexing is.
| pen2l wrote:
| Maybe Google can by traversing the virtual DOM and other
| trickery but it's not as simple for other small players.
| Moreover, in a healthy web I should be able to easily
| deeplink to something I'm thinking about without jumping
| through hoops. The SPA web is not as easily discoverable
| and connected as it is very much meant to be. I think there
| are valid arguments to be made for SPA, like that SPA need
| to SPA because they are not just a series of pages and
| documents but complex applications which need to be that
| way (though I would still tread with caution: I remember
| java applets and javascript bits doing complex things,
| submerged within pages, and that was all fine).
| robertoandred wrote:
| You can deeplink with SPAs just fine.
| endisneigh wrote:
| You are conflating things. With urls you can link fine,
| spa or not. It's possible to design a single page server
| side rendered page without properly implemented links.
|
| The things you are describing are not attributable to spa
| inherently, just a poorly designed site
| manigandham wrote:
| That's literally what the article is explaining. Better routing
| system, and bundling, and a simpler optimized config for
| output.
| throwaway4good wrote:
| But that is a lot of complexity and dead functionality to
| drag into a project for just that? Surely next.js's router is
| not that different from React router.
| adchurch wrote:
| In our experience, using Next.js reduced our complexity,
| because it has out-of-the-box implementations (and simple
| configuration) for lots of stuff we had to manually hack
| around with CRA as our project grew
| j-krieger wrote:
| Well true SSR allows you to send zero javascript to your
| client, so this is ultimately a net positive. My site is
| written entirely in React because I like working with it, but
| thanks to Next.js you as a client will never know the
| difference between that and me serving static HTML in the first
| place. All pages, subpages and blog posts ship in a relatively
| tiny 200KB bundle.
| sgdesign wrote:
| Unless you're talking about SSG and not SSR, I think one
| potential issue would be that React's SSR process is pretty
| slow and costly, at least from what I understand. I have to
| confess I haven't heard of a pure-SSR React app before, as
| you wouldn't get many of React's benefits if it's just being
| used as a templating language.
| jsnk wrote:
| What cause the performance improvement?
|
| Maybe I missed this detail. I couldn't find anything on why the
| performance improvement happened when they moved from CRA to
| Nextjs
| adchurch wrote:
| I explained it a bit more here:
| https://news.ycombinator.com/item?id=33319806
|
| Let me know if this still doesn't answer your question though!
| adchurch wrote:
| I'm one of the engineers that worked on this - would love to hear
| any thoughts or feedback anyone has! How does your team deploy
| your Next.js frontend?
| bgirard wrote:
| I'm curious where the majority of the win came from? Do you
| have a before & after trace handy to compare what changed?
|
| Looks like you opted not to use SSR, which I think is a good
| choice for smaller teams. CSS changes are unlikely to account
| for a large performance win. Did you use a CDN before? Perhaps
| the biggest win was moving to a better CDN + built-in
| preloading/prefetching provided by NextJS?
| adchurch wrote:
| > I'm curious where the majority of the win came from?
|
| Great question! The boost can be explained by JS vs. raw
| HTML+CSS performance.
|
| In the past, we sent a dummy loading screen but we then had
| to download tons of JS + run that to even show a "real"
| loading screen (i.e. page-specific loading screen).
|
| Now, the HTML response (which you can inspect yourself, `curl
| https://my.causal.app`) already has a skeleton of the page,
| which doesn't need any JS to download and run before showing
| the "real" loading screen.
|
| The UX is better because users spend noticeably less time
| staring at a blank screen and there's much less layout shift
| too!
| bgirard wrote:
| Which metric improved by 70%? Time to show the skeleton? I
| agree the skeleton is quite good. I see it takes about
| 350ms to show the skeleton and about 1s to show my content.
| adchurch wrote:
| Yep - the metric was First Contentful Paint, which is
| basically the time-to-skeleton in our case :)
| JayStavis wrote:
| > backend API calls will be very fast because of colocation on
| GCP
|
| Any chance you guys measured this speed difference? Was there a
| path considered to locally cache api responses on the vercel
| server or in middleware somewhere?
|
| Trying to reason about a similar decision right now. There's
| probably a simple way to cache hot backend request/responses to
| get static-like speeds?
| adchurch wrote:
| > Any chance you guys measured this speed difference?
|
| No, but we actually can get some comparison, since as I
| mentioned we host preview apps on Vercel! I did some quick
| tests right now, and it looks like based on logs, the API
| request to our Node backend takes:
|
| - From Vercel: ~300ms worst case, ~40ms best case
|
| - From within GCP: ~120ms worst case, ~20ms best case
|
| These numbers are very approximate, but hopefully still
| insightful! And I'm not sure about the cause of the variance,
| there are quite a few links in the chain that could be at
| fault.
|
| > Was there a path considered to locally cache api responses
| on the vercel server or in middleware somewhere?
|
| We do cache the responses using a CDN; adding another layer
| of caching beyond this wouldn't help much since at that point
| we need to fetch fresh results anyway.
|
| > There's probably a simple way to cache hot backend
| request/responses to get static-like speeds?
|
| Yes, the CDN cache I mentioned is almost instant in good
| conditions (~2ms on my internet connection) - the problem is
| sometimes you do actually need updated data, and having huge
| variance between the cached response speed and the uncached
| response speed could be undesirable for users.
| JayStavis wrote:
| thanks for those figures! It makes sense on the cache
| invalidation given the type of content Casual is serving.
|
| It will be interesting once Vercel offers colo'd data
| sources and more with their edge rendering, which they just
| announced: https://vercel.com/blog/regional-execution-for-
| ultra-low-lat...
| mikojan wrote:
| The problems described in the "Routing" section are trivially
| automated. You do not even need a separate data loading library
| because react-router-dom ships one.
|
| The problems described in the "Styles" section would have been
| solved by migrating to a modern bundler: vite.
| adchurch wrote:
| > The problems described in the "Routing" section are trivially
| automated. You do not even need a separate data loading library
| because react-router-dom ships one.
|
| I'm not sure which problems you mean; fwiw the routing section
| is more intended to explain how we migrated `react-
| router`-style routing to `next/router`-style routing :)
|
| > The problems described in the "Styles" section would have
| been solved by migrating to a modern bundler: vite.
|
| I think the problems with impure styles (e.g.
| `styles/button.scss` referenced in the post) would have been an
| issue no matter what bundler we used, right? Which problems are
| you referring to?
___________________________________________________________________
(page generated 2022-10-24 23:02 UTC)