Why I won't use Remix

Response "to Why I won’t use Next.js" by Kent C. Dodds

Why I won't use Remix

A few weeks ago, the tech world was abuzz with Kent C. Dodds' article with the attention-grabbing title "Why I won't use Next.js." In it, Kent criticizes Next.js and uses Remix as an example of a framework that solves every problem. Well, it's not entirely accurate... Below you'll find my response to each of the points brought up by Kent.

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 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: the 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 in Kent's is very subjective. From my perspective, not much has changed except for the velocity - the development and implementation of new things in React have 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 meta-framework can make use of them. Remix intentionally and deliberately does not use them.

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 meta-frameworks. The unstable version of React is labelled with the experimental tag. I hope this clarification addresses the doubts.

Too much magic

Contrary to what the article seems to suggest, Next.js has fully embraced the Web APIs. Forms are just regular form elements, API Routes use Request and Response, there's a strong emphasis on fetch, and so on... Definitely has less magic than in previous versions.

In contrast, Remix is heading in the opposite direction:

  • instead of standard async/server components they have loader

  • instead of standard server actions and "use server" they have action

  • instead of standard "use client" they have code splitting

  • instead of standard async components they have defer and SSR ErrorBoundary

  • instead of standard <form action> they have Form

  • instead of standard useFormStatus, useOptimistic they have useNavigation/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 cache handling to it. Kent compares this to overwriting prototypes of built-in objects by MooTools, which, seems to me, is 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 too many 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 like Next.js to add their cache handling.

Is it perfect? Some might argue it's far from it and I think I agree. But does it work? Yeah, it does. Does it break your code? No; at least not if implemented correctly.

Complexity

The author claims that Next.js is becoming too complex, and as examples of this, he mentions the APIs added to React.js and not Next. Dan Abramov commented on this quite nicely, so I guess there's not much more to add.

Stability

If I understand the 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 just recently. 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 for 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. I've spent some time going 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, the article 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 far from being objective and we pointed out multiple biased examples used to present Remix as better, faster, stronger.

Kent C. Dodds' article is certainly more balanced, however, I still managed to find some inaccuracies in it. I hope this helps you build a more balanced and educated opinion about both Next.js and Remix.

Do you agree? Do you think I've made any mistakes in my assessment? Let me know your thoughts in the comments!

PS Kent is selling his Remix course on a website written in Next.js. That's just inconsistent, isn't it?

  1. github.com/vercel/next.js/tree/canary/examples/with-docker-compose

  2. github.com/vercel/next.js/tree/canary/examples/with-docker-multi-env

  3. github.com/vercel/next.js/tree/canary/examples/with-docker

  4. nextjs.org/docs/app/api-reference/next-config-js/incrementalCacheHandlerPath

  5. remix.run/blog/react-server-components#remix-can-take-full-advantage-of-rsc

  6. twitter.com/ryanflorence/status/1686757173202997249

  7. github.com/angular/angular/blob/HEAD/packages/zone.js/STANDARD-APIS.md#browser

  8. twitter.com/zaiste/status/1717595898312642786

  9. react.dev/blog/2023/05/03/react-canaries

  10. youtube.com/live/XKeN9WsUAzM

Did you find this article valuable?

Support Michał Miszczyszyn by becoming a sponsor. Any amount is appreciated!