Independence
OpenNext exists because Next.js is difficult to deploy anywhere but Vercel.
The sentence could be true if it read "OpenNext exists because deploying Next.js on AWS with serverless is challenging." And that's absolutely true; it's quite complex. Complex to the extent that Remix also doesn't provide a ready-made AWS serverless template either, contrary to what Kent seems to suggest in his article.
OpenNext uses SST (Serverless Stack) – a project designed to simplify the deployment of applications on AWS. It is not specific or targeted only at Next.js; quite the opposite: SST website mentions Next.js, Astro, SvelteKit, SolidSite… and Remix.
Now, does Vercel have an interest in making it easier to use Next.js on other hosting solutions, even though they offer their paid services? Of course not. Nonetheless, in the Next.js repository, you can find examples of how to do that 1 2 3, and the documentation even describes how to implement your own Data Cache.
Next.js is eating React
Ever since then, the React team has felt much less collaborative.
This section of Kent's article lacks specific arguments or examples, and it's difficult to agree or disagree with someone's feelings. From my perspective, not much has changed except for the velocity - the development and implementation of new things in React has accelerated significantly over the past year. But it still happens publicly, through an RFC process, new features land in the canary
, and only much, much later in the stable version.
The issue for the Remix team might be that it wasn't them, but the Next.js team that was the first to utilize the new features of React. We're talking about React Server Components and Server Actions – things that aren't specific to Next.js but are part of React itself, and essentially any metaframework can make use of them. Remix intentionally and deliberately does not use them, so it's even more less clear to me what is Kent trying to convey through this point of criticism.
Experimenting on my users
Features that Next.js is shipping as stable are in the canary release of React.
Yes, exactly! However, the term canary
in React has a slightly different meaning than in other projects. The React maintainers state that by "canary," they mean a version of React.js that is ready for adoption in metaframeworks. The unstable version of React is labeled with the experimental
tag. This clarification likely addresses the doubts raised in this paragraph, doesn't it?
Too much magic
Contrary to what Kent says, Next.js has fully embraced the Web API. Forms are just regular form
elements, API Routes use Request
and Response
, there's a strong emphasis on fetch
, and so on... Definitely less magic than in previous versions.
In constrast, Remix is heading in a completely opposite direction:
- instead of standard
async/server components
they haveloader
- instead of standard
server actions
,"use server"
they haveaction
- instead of standard
"use client"
they havecode splitting
- instead of standard
async components
they havedefer
and SSRErrorBoundary
- instead of standard
<form action>
they haveForm
- instead of standard
useFormStatus
,useOptimistic
they haveuseNavigation
/useFetcher
And for now, they don't plan on changing that.
What's outrageous for many people is that Next.js overrides the fetch
function and adds its own cache handling to it. Kent compares this to overwriting prototypes of built-in objects by MooTools, which is either mere demagoguery or a complete misunderstanding of the problem.
Adding or overwriting properties in prototypes is indeed problematic for compatibility and the functioning of code originating from different sources.
However, wrapping a global function in your code and invoking the original function underneath doesn't create issues for end users. Interestingly, Next.js isn't setting a precedent here. For example, Angular overwrites practically all global functions. As for other interesting examples, Cloudflare, a company involved in developing Web APIs, also overwrites fetch
in their workers in a manner similar to Next.js to add their own cache handling.
Complexity
The author claims that Next.js is becoming too complex, and as examples of this, he mentions the APIs added to React.js, which Remix also utilizes. The plot thickens.
Dan Abramov commented on this quite nicely, so I guess there's not much more to add.
Stability
If I understand Kent C. Dodds' intention correctly, the thesis of this paragraph is: "Remix had only 2 versions, so it's more stable than Next.js, which had 14 versions." This is not only absurd but also entirely untrue. Let's take a closer look.
Next.js has been in development since November 2016, celebrating its 7th birthday in a few days. The first release of Next.js was... 1.0.1
. To follow SemVer, from that point on, every modification of Next.js's public API had to result in a major version bump, meaning 1 to 2, 2 to 3, and so on... Also, note that version 13 was bumped to 14 solely due to the requirement of a higher Node.js version; there were no other breaking changes.
Remix adopted a different versioning strategy. The first public release marked as 0.8.0
was released in 2021. Versions starting with 0.
, according to SemVer, can introduce breaking changes without the need to bump the major version, so 0.8.0
becomes 0.9.0
, not 1.0.0
. Therefore, I've spent some time to go through Remix's entire changelog and found 12 breaking changes. Had the Remix team adopted the same versioning model, they would be at version 13 after two years, just like Next.js is after seven. Makes you think, doesn't it?
Additionally, Kent seems to suggest that Next.js doesn't provide a migration path from old versions to new ones – but that might just be my mistaken impression. Anyway, migrating from Next.js 12 to 13 took 3 minutes – the changes are minimal, and the new router is entirely optional. The previous routing method will be supported for a long time, for many years. On the other hand, migrating from 13 to 14 took us literally 30 seconds in a production project.
Summary
A year ago, Zaiste and I recorded a video "Remix Marketing Exposed" (in Polish), in which we dissected the Next.js and Remix comparison published by the Remix team. We demonstrated that the content therein is not just an unobjective marketing stunt but straightforward lies and manipulations without a shred of shame. Kent C. Dodds' article is certainly more balanced, and I'll leave the final assessment of intentions to you.
Ironically, Kent is selling a Remix course on a website written in Next.js.
Links
- github.com/vercel/next.js/tree/canary/examples/with-docker-compose
- github.com/vercel/next.js/tree/canary/examples/with-docker-multi-env
- github.com/vercel/next.js/tree/canary/examples/with-docker
- nextjs.org/docs/app/api-reference/next-config-js/incrementalCacheHandlerPath
- remix.run/blog/react-server-components#remix-can-take-full-advantage-of-rsc
- twitter.com/ryanflorence/status/1686757173202997249
- github.com/angular/angular/blob/HEAD/packages/zone.js/STANDARD-APIS.md#browser
- twitter.com/zaiste/status/1717595898312642786
- react.dev/blog/2023/05/03/react-canaries
- youtube.com/live/XKeN9WsUAzM