Why NextJS Sucks
I’ve used NextJS for static websites because the experience with amplify hosting is so insanely easy. The fact that I go on the AWS console and connect a github repo and it just works, and runs with lambda, and is super cheap (unless I get DDOS’d)… that’s just too good to say no to in some cases.
Even though server side rendering hasn’t been required in years in order for google to index and find your content, the developer experience for toy websites is too good to pass up.
But for a complex SaaS project, I see very few benefits and some serious downsides of NextJS.
NodeJS sucks for SSR
𝐑𝐞𝐚𝐜𝐭 𝐫𝐞𝐧𝐝𝐞𝐫𝐢𝐧𝐠 𝐨𝐧 𝐭𝐡𝐞 𝐬𝐞𝐫𝐯𝐞𝐫 𝐚𝐝𝐝𝐬 𝐚 𝐝𝐢𝐦𝐞𝐧𝐬𝐢𝐨𝐧 𝐨𝐟 𝐜𝐨𝐦𝐩𝐥𝐞𝐱𝐢𝐭𝐲 𝐭𝐨 𝐭𝐡𝐞 𝐚𝐩𝐩𝐥𝐢𝐜𝐚𝐭𝐢𝐨𝐧 𝐛𝐞𝐜𝐚𝐮𝐬𝐞 𝐲𝐨𝐮’𝐫𝐞 𝐦𝐚𝐤𝐢𝐧𝐠 𝐍𝐨𝐝𝐞𝐉𝐒 𝐝𝐨 𝐬𝐨𝐦𝐞𝐭𝐡𝐢𝐧𝐠 𝐢𝐭’𝐬 𝐫𝐞𝐚𝐥𝐥𝐲 𝐛𝐚𝐝 𝐚𝐭 𝐝𝐨𝐢𝐧𝐠.
NodeJs is single threaded. In the ideal case that it’s designed for, requests should be I/O bound. A complex page requiring much SSR will hamstring the ability to serve concurrent requests. Here is a talk by a former coworker of mine on his experience optimizing server side rendering through large demand spikes.
Now, of course, most apps (including yours) are not going to have the same kind of spikes that Walmart has on black Friday. But you always gotta think about what you’re gaining in exchange of what you're giving up. From what I recall, my friend’s Walmart situation ended up boiling down to NodeJS getting hung up on page rendering for too long, then the operating system’s http request queue would expand too large, because they weren’t configured for load shedding, and the servers would become unresponsive as described in that load shedding article.
The autoscaling infrastructure would come to the rescue and constantly spin up new servers, but they spent millions of dollars on that, and still experienced availability loss (users getting a broken experience and having to reload). In order to fix it my friend ended up basically having to inject setTimeouts all over the place when rendering the app.
Now of course there’s ways to avoid all of this such as static site pregeneration, or hosting on serverless. This is part of the reason why serverless is a popular choice for NextJS. But my favorite way of avoiding this particular bit of complexity is just not server-rendering react in nodejs.
Security takes a back seat to coolness
Many nextJS features require allowing the browser to inject inline scripts. Nextjs’s implementation of suspense, and also usage of the appDir feature (which you basically always use), using next/font
, and anything you put in your rootLayout all gets injected into the app as inline scripts.
Open up any nextJS website and you'll see a bunch of inline scripts like the screenshot below, from one of my NextJS pages:
Those are a bunch of inline scripts. Inline scripts are bad, because the only actually reliable way to prevent reflected XSS attacks is with content security policy headers that prevent the execution of inline scripts. A strong CSP policy is the golden standard for XSS prevention. And the main thing you need to do from a CSP standpoint is to avoid inline scripts.
If you just instruct the browser to not execute inline scripts, stored XSS is impossible. But if you use any of the NextJS features that require inline scripts, you cannot have a CSP policy to forbid inline scripts. Because of that, you have to settle for something worse, which is allowing only inline scripts that match a certain nonce (computed randomly at load time).
In order to do that with nextJS, you have to write a significant amount of code and jump through hoops (see docs on how to do it if you want your head to spin). Fun side effect of this is, even if you put a CDN in front of your NextJS cluster, there won't be any edge location caching because the nonce has to be different for every session (if it's not, it defeats the purpose of the nonce and you might as well just allow inline scripts).
NextJS doesn’t respect your time
Their API is incredibly unstable and they break it all the time. Basically every 6 months. The upgrade from 13 to 14 was hard.
The hosting infrastructure is much worse
If you host a SPA with a CDN, you can serve 30 million customers a month for a few bucks. If you use NextJS instead, you have a couple of choices:
- Go serverless and be vulnerable to insanely massive bills from a simple naive DDOS
- Use ECS/EC2 and then have the potential to lose availability because you scale up too slow during a demand spike (related to point 1 above)
Both choices suck. Both choices will cost you a lot more.
In addition, you give up the globally distributed nature of a CDN, which caches files near your users. It also handles caching (based on e-tags) between your user and the edge location. It’s a LOT to give up and I’m convinced that many people who think this is a good idea just don’t know wtf a CDN even is, or all it does for you. They’re like the developer in the hero picture of this article.