Next.js Made Me a Bad Engineer

Next.js Made Me a Bad Engineer

The Realisation

I was tasked with porting our Single Page Web Application (SPA) to a Server-Side Rendered (SSR) setup.

The goal was simple:
provided a set of pages, they need to be made SEO-friendly.

And right off the bat, 2 classic options came to my mind: SSG & SSR.

The problem with statically generating all pages upfront (SSG) was build-time, I estimated it to be ~11 hours.

The problem with SSR was speed, it took ~5 seconds before content was seen on the page.

The best of both worlds seemed ISR-like setup, where as requests come in, we cache the content & serve the cached content for X amount of time and after time's up the cache is invalidated for the route & content is re-fetched from the origin server.

The problem was the framework.

Or at least, that's what my naive vercel-fanboy brain thought (sorry theo).

You see, I was working on a Vue.js project flavoured with a framework called Quasar.

And apparently, you can't do something like this there...

// courtesy of Vercel/Next.js (same thing)
export const revalidate = 3600

So, in the next standup, I called out how Quasar doesn't support ISR and therefore is not the right choice for us here & we should move to a different & more popular framework like Nuxt because it EXPLICITLY supports ISR.

The majority of responses were positive to this suggestion but one response stood out:

that seems good but did you try hooking up a CDN first?

The Problem with Me (and you)

I am not new to the field, I wrote my first Javascript code 3 years ago and I'm something of a Web Developer myself.

Even after having a couple years of experience, I fell into the framework trap.

Just because a framework solves a problem doesn't mean that the problem can't be solved without the framework.

-me

And what's more problematic is that my suggestion was well-received by the majority.

The Solution

Use CloudFront for caching and Cache-Control headers in the response.

Cache-Control: public, max-age=604800, stale-while-revalidate=86400

I'm embarrassed by how simple it is.

READ THE FRICKIN DOCS:

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Expiration.html#stale-content

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control

https://docs.netlify.com/platform/caching

Implementation Details

SEO Friendliness

Focussing on our main problem: make the site SEO friendly.

With SPA, in any library/framework, the rendering is happening on the browser (client-side).

Any SEO crawlers looking to index your site usually have javascript disabled, which means that all of that rendering is gone and the crawlers will just see a blank page.

"Disable Javascript" while in developer mode in your browser to get an idea of what exactly the crawlers can see ;)

So, my first step was to migrate the application to SSR (Server-Side Rendering).

Now, with SSR, all that rendering is happening on the server and at last, the server gives out a nicely populated (rendered) HTML.

Caching Mechanism

In my little bit of research, I found 3 plausible options:

  1. Cloudflare Cache

  2. Netlify CDN

  3. AWS CloudFront

I chose AWS CloudFront.

Reasons for not going with anyone else:

  • Cloudflare CDN - had limits of 512MB on caching file sizes (really don't know why, could also be my doc-reading skill issues)

  • Netlify CDN - "$55 per 100GB" for bandwidth above free trial? please!

Actually, I've been thinking... It's about time we cut some slack for AWS.

Obviously, AWS is gonna be a skill issue for front-end people who like one-click deploys and outrageous serverless pricings.

But the services it provides far outweigh its crappy-looking website's UX which by the way they've updated to a better UX a while ago and I blame the culture around "if you don't have a good-looking website, your business is crap".

And AWS's CloudFront solution makes the most sense, very neatly decoupling the cache layer from the origin server and the tech stack used. Here's a diagram I made to make you understand it better.

When setting up, CloudFront requires your server's URL and then provides you a ".cloudfront.net" URL.

This ".cloudfront.net" URL is the cache layer and the caching behaviour is controlled by the "Cache-Control" header supplied in response by your origin server.

Call For Discussion

I have some spicy hot takes here for you to fight me on and I'll try my best to stand by them in the comments :)

Do you think Next.js and its introduction of Server Components is any good? Or for that matter, is the general direction of Vercel good for Engineers?

Because I don't think since getServerSideProps days there were any meaningful features at all introduced that ackshually solved problems.

With Vercel's "frontend cloud" philosophy, we will be broke with the unreal pricing just for the illusion of DX.

If you complain about the developer experience you're not a developer at all.

-me again

Take me up on that in the comments, thanks for reading!