[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)