Blog

How to Make a Stupid Fast Site With Next.js

There are a lot of approaches you can take.
Oct 25, 2024

I’ve been using React for over a decade and am really good at making it fast. A lot of it comes down to bundle sizes. But with this site I wanted the power of SEO — cue Next.js. A lot of startups use Next (really for no reason) for their web apps and the performance is… fine. I don’t like fine though.

To start, some basic tips are: use their font and image optimization setups, they work. CSS-in-JS, even if you can get it to work properly is always going to be slower then regular CSS. I opted for Sass modules since it adds some features and scoping.

When you make a page in Next it can identify if it can be static and generate the markup for it once at build time, which is nice. Most of this site is static, minus the blog pages, so I got good performance out of the gate, but the blog pages? Slow.

The Contentful API is slow. Even with only a few posts it can easily take 120+ ms to respond on it’s own. Not exactly blazing fast. So step one was ISR for the blog post pages. Incremental Static Regeneration can work by either in a given time period regenerate the static page or you can manually invalidate the builds yourself. A time based approach was fine for me. To set it up you essentially move your data fetching to getStaticProps, also returning the invalidation timespan, and create a getStaticPaths method. getStaticPaths is used to generate each one of the blog post pages, but fetching the IDs and returning them. A little strange, but it’s easier than it sounds. Every 2 minutes my posts are regenerated, in case there are new ones, a removal, or a change. Easy enough.

But the page that lists all of the posts was still slowwww. So I tried getting their data cache to work. It was a pain. I had to fight with it, but after getting it working, my webhook from contentful to tell my app to invalidate the cache didn’t work, at all. This is changing in Next 15 anyway, but I’m pretty sure my problem was not using the new app router. So on to a new idea.

I also tried Redis, but the problem with services, especially databases or cache they aren’t co-located with your web servers is latency, and I felt it. The responses were sometimes faster, but sometimes way slower. Sick.

So I hacked ISR. The thing about it is it only works if there’s a slug in your URL and mine did not. So for now, I faked it. My blog list page can take a slug with the page number, bur in getStaticPaths I only return one page. And it worked! Now all my pages, even if they are dynamic are served statically.

But there was one more problem. I hosted it on vercel and the latency isn’t great. We are still talking 500ms for a static asset essentially. They actually (wrongly) advise against proxying through Cloudflare, but I did it anyway. Since Next already sends good caching headers, I basically went into Cloudflare and enabled caching for static assets and turned on all of the other speed related enhancements and… 100 ms (give or take a few ms) for any page to load! Stupid fast. I love it! I went in and removed my loading progress bar, because to most people the site and pages look like they load instantly.

In summary: use their optimizations, don’t use CSS-in-JS, take advantage of ISR when you can, and use a proper CDN like Cloudflare and it will be blazing fast. You can’t use ISR for most web apps because the data has to be up to date, but for some blog posts? Users can wait 2 minutes until the next one drops.