Remix vs Next.js

Auteur(s) de l'article

Au-delà de ce titre aguicheur, il s'agit de comparer sous divers angles, Remix, le bientôt plus si nouveau framework des créateurs de react-router et de unpkg, et Next.js que nous utilisons activement à l'agence depuis quelques années. L'idée est de comprendre les forces et faiblesses de chacun afin de déterminer quels types de projets peuvent bénéficier de l'un ou l'autre.

Disclaimer

Cela peut sembler évident, mais toute cette comparaison se base sur les versions actuelles de Remix (1.18) et de Next.js (13.4). Beaucoup d'aspects vont probablement continuer d'évoluer dans les prochains mois et rendront certaines comparaisons totalement obsolètes, mais tant mieux.
Personnellement, je trouve qu'il n'y a pas eu d'aussi belle époque qu'actuellement pour faire du développement JavaScript; toutes les solutions et tous les frameworks proposés sont excellents (même Angular), tous vont offrir des résultats très aboutis et une expérience de développement aux petits oignons !

React au centre

Avant d'aller plus loin, il est également important de préciser que ces deux frameworks sont construits autour de React.js. Désireux de demeurer, pour l'instant, dans cet écosystème, voici pourquoi nous avons choisi de confronter Next.js à Remix, et pas à Nuxt ou Sveltkit qui n'en demeurent pas moins intéressants.
React n'étant “qu'une” librairie de gestion d'interfaces utilisateur, ces frameworks apportent des solutions pour gérer les routes, le rendu et la logique coté serveur et tout l'outillage qui va servir à faire tourner, builder et déployer notre application.

La philosophie de Remix

Premièrement, il s'agit de séparer très clairement à la logique serveur et cliente. Contrairement aux débuts de Next.js avec son getInitialProps exécuté tantôt sur le serveur, tantôt dans le navigateur; Remix marque clairement la frontière entre serveur et client par le nom des fichiers xyz.client etxyz.server et par les méthodes exposées et utilisées par les routes.
Deuxièmement, il y a une vraie volonté de Remix de se rapprocher au plus prêt des standards du web. D'une part pour éviter toutes frictions d'adoption, mais aussi pour être le plus cohérent possible. Cela passe par les attributs HTML, l'utilisation de la Fetch API coté serveur ou par le fonctionnement et la gestion des formulaires.
Ensuite il s'agit d'utiliser JavaScript à bon escient : améliorer l'expérience utilisateur·trice. Évidemment que tout le langage de notre application Remix est en JavaScript (TypeScript idéalement), mais le JavaScript envoyé à l'internaute se veux le plus léger et performant possible. Et contrairement à Next.js, Remix nous offre l'option de désactiver l'hydratation React d'une ou plusieurs routes par un simple export const handle = { hydrate: false; };.
Pour finir, Remix favorise l'abstraction minimum. Il s'agit de garder en général les termes au plus proches de l'origine,comme Next.js sait également très bien le faire.

Remix en deux mots

Maintenant qu'on situe sa philosophie : qu'est-ce que propose Remix ?
Pour la faire courte, Remix c'est :
  • Un compilateur (basé sur esbuild)
  • Un serveur HTTP
  • Un framework serveur MVC, qui va laisser le soin du modèle aux développeurs·euses selon les besoins du projet
  • Un framework client avec l'aide de React
Remix offre des “stacks” ou templates de projets qui vont comprendre une préconfiguration :
  • de la base de données
  • des processus de déploiements
  • du système d'authentification
  • des tests
  • des linters et de TypeScript

Router

Le premier gros avantage d'utiliser Next.js ou Remix réside dans leurs routers. À l'époque où j'écris cet article (en juillet de l'an de grâce 2023), Next.js possède deux routers; le Page Router et l'App Router. Je ne vais pas rentrer dans les détails ici, mais certaines comparaisons ne vont se faire qu'avec l'un ou l'autre et parfois, les deux. Maintenant, l'App Router est encore relativement frais, donc il est possible que certaines de ses possibilités m'échappent encore.
Ce qu'il faut déjà retenir c'est que tous ces routers, Remix compris, sont file-based; ce qui veut dire que l'arborescence et le nom des fichiers vont définir les URLs (routes) de notre application. Maintenant, mis à part quelques différences de syntaxe, Next.js et Remix offre les mêmes possibilités dans le naming pour générer des segments de route dynamique. On notera toutefois que la version 2 de Remix offre la possibilité de mettre de côté les répertoires imbriqués au profil de simple . dans le nom des fichiers pour marquer la hiérarchie.
Pour ce qui est de l'anatomie d'une route, soit le fichier qui va rendre notre page finale, les deux frameworks fonctionnent d'une manière assez similaire : exporter une méthode par défaut pour le rendu et d'autres méthodes pour gérer les spécificités. Dans les choses très bien pensées chez Remix, il y a l'export des méthodes loader pour exécuter une logique GET coté serveur et action pour exécuter une logique POST, PUT, etc coté serveur. Next.js offre quelque chose de similaire avec getServerSideProps pour la logique GET dans le Page Router ou les Server Actions pour la logique POST, PUT, etc dans l'App Router.
Très pratique également, Remix offre de base un CatchBoundary et un ErrorBoundary pour les interceptions. Il est également de redéfinir très facilement les headers, meta et links d'une route en les exportant sans passer par un fichier _document.tsx ou layout.tsx comme dans Next.js.
Nos deux frameworks gèrent la revalidation d'une route; Remix avec la méthode shouldRevalidate qui doit retourner un boolean et Next.js avec l'option revalidate du Page Router ou la méthode revalidatePath de l'App Router.

Composants, Hooks, Utils

Remix comme Next.js va proposer des composants React qui vont simplifier l'intégration de certaines mécaniques. Les deux exposent les composants équivoques Link et Script. Remix va proposer en plus Await, Form, Links, LiveReload, Meta, NavLink, Outlet, PrefetchPageLinks et ScrollRestoration, mais contrairement à Next.js, pas de composant Image.
Next.js offre déjà quelques hooks comme useRouter ou useParams, mais Remix en propose six fois plus. Beaucoup sont directement hérités de react-router comme useParams ou useNavigate, et d'autres uniquement pour Remix comme useLoaderData ou useActionData. Ce qui est appréciable dans cette diversité, c'est la simplicité d'usage faite de ces hooks.
Pour finir, comme Next.js, Remix offre des utils pour gérer des choses comme les cookies et les redirections. Chacun a ici sa subtilité.

En conclusion

Vous avez directement sauté à ce chapitre, tant mieux, voici quel framework choisir selon votre projet. En soi, les deux proposent une approche et des fonctionnalités très similaires, mais aussi une très bonne expérience de développement.
Le premier point déterminant est la capacité à faire du Static Site Generation (SSG), Next.js en est capable avec son Page Router. Il permet de prégénérer les pages et de les revalider (rebuilder) à la demande. Remix n'est pas positionné dans ce sens, plutôt que de générer les pages, il pousse à s'appuyer sur les performances de systèmes distribués. Maintenant, si vous voulez faire un site vitrine ou un blog avec du SSG, Remix n'est pas pour vous (contrairement à Astro 🤫).
Sachant cela, on comprend rapidement que Remix s'adresse à des projets plus orientés applicatifs au même titre que l'App Router de Next.js.
En dehors de ça, le deuxième et dernier facteur déterminant va résider dans la préférence personnelle entre la philosophie, la syntaxe et les subtilités de Remix ou de Next.js. Mettez les mains dedans et choisissez lequel vous parle le plus pour développer votre application. Dans tous les cas, vous n'allez pas faire de mauvais choix !