Web Standards Framework

Remix

Remix est le framework React privilégiant les standards du web. Il s'appuie sur HTTP, les formulaires et l'amélioration progressive pour que votre application fonctionne avant même que le JavaScript n'arrive.

intermediate13 min readUpdated 15 sept. 2026
posts.$slug.tsx
tsx
// app/routes/posts.$slug.tsx
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";

export async function loader({ params }) {
  const post = await getPost(params.slug);
  if (!post) throw json({ message: "Not found" }, { status: 404 });
  return json({ post });
}

export default function Post() {
  const { post } = useLoaderData();
  return <article>{post.title}</article>;
}
Basé sur
React
Modèle
Routes imbriquées
Données
loaders
Mutations
actions
Philosophie
Priorité aux standards du web
Actuellement
Fusionné dans React Router v7

Pourquoi c'est important

Pourquoi Remix choisit une voie différente

Amélioration progressive

Les formulaires et la navigation fonctionnent sans JavaScript, puis deviennent plus rapides et fluides une fois celui-ci chargé.

Routes imbriquées avec données

Chaque route charge ses propres données et gère ses propres erreurs, en parallèle avec ses routes sœurs.

Moins de pièces mobiles

Les loaders et les actions remplacent l'enchevêtrement habituel d'états clients, d'effets et d'appels API.

Le tableau complet

Les trois idées fondamentales de Remix

Les routes possèdent leurs propres données, les mutations sont des formulaires, et tout se dégrade gracieusement sans JavaScript.

Routes

Structure

Les routes imbriquées définissent l'URL, la mise en page et la limite des données en un seul endroit.

Loaders et actions

Données

Des fonctions serveur qui lisent les données avant le rendu et gèrent les mutations provenant des formulaires.

Standards du web

Fondation

Les requêtes, les réponses, les formulaires et les headers sont des primitives de la plateforme, et non des abstractions du framework.

Remix en un coup d'œil

Le cœur de Remix

Routes imbriquées

Les modules de route s'imbriquent pour correspondre à la hiérarchie de l'UI et chargent les données en parallèle.

Loaders

Fonctions serveur qui fournissent des données à une route avant son rendu.

Actions

Fonctions serveur qui gèrent les soumissions de formulaires et les mutations.

Formulaires

De vrais formulaires HTML qui fonctionnent sans JavaScript et s'améliorent automatiquement.

Error boundaries

Gestion des erreurs par route qui permet au reste de la page de rester actif.

Resource routes

Routes qui retournent des données au lieu d'une UI, utiles pour les API et les webhooks.

Un bref aperçu

D'un Remix du web à React Router

  1. 2020

    Annonce de Remix

    Les créateurs de React Router présentent un framework basé sur les standards du web.

    20
  2. 2021

    Open source

    Remix est publié publiquement et attire l'attention grâce à son modèle de chargement de données.

    21
  3. 2022

    Remix 1.0 et Shopify

    Une version stable est publiée, et Shopify acquiert l'équipe et adopte Remix.

    22
  4. 2024

    React Router v7

    Les idées de Remix sont intégrées à React Router, et Remix devient son mode framework.

    24
  5. Aujourd'hui

    React axé sur les standards

    Le modèle perdure via le mode framework de React Router, avec la même philosophie.

    Aujourd'hui

Le guide complet

Remix: Tout ce que vous devez savoir

Qu’est-ce que Remix ?

Remix est un framework React basé sur les standards du web. Alors que de nombreux frameworks s’éloignent de la plateforme via des abstractions, Remix s’appuie dessus : les requêtes et réponses HTTP, les formulaires HTML, les liens, les headers et les cookies en sont le fondement, et le framework les améliore plutôt que de les remplacer.

Le résultat est une application qui fonctionne avant même que le JavaScript ne soit chargé. Les formulaires sont soumis, la navigation via les liens opère et les données s’affichent, car le serveur effectue le travail. Une fois que le JavaScript est chargé, ces mêmes interactions deviennent instantanées et partielles. Cette propriété s’appelle l’amélioration progressive (progressive enhancement), et c’est l’idée maîtresse de Remix.

En 2024, l’équipe de Remix a intégré le framework dans React Router v7, où il perdure sous la forme d’un “framework mode”. Les concepts et les API restent inchangés, tout ce qui est présenté ici s’applique donc aux deux.

Routes imbriquées

Les routes sont des fichiers situés sous app/routes, et les points dans les noms de fichiers correspondent aux segments d’URL.

app/routes/
├── _index.tsx              # /
├── posts._index.tsx        # /posts
├── posts.$slug.tsx         # /posts/:slug
├── posts.$slug.edit.tsx    # /posts/:slug/edit
└── api.health.tsx          # /api/health

Les routes s’imbriquent pour correspondre à l’interface utilisateur. Une route parente rend un layout partagé et un <Outlet />, et les routes enfants sont rendues à l’intérieur de celui-ci. Comme Remix connaît l’intégralité de l’arborescence des routes, il peut charger les données d’une page et de toutes ses routes imbriquées en parallèle plutôt que via un effet de cascade (waterfall).

// app/routes/posts.tsx
import { Outlet } from "@remix-run/react";

export default function PostsLayout() {
  return (
    <div className="posts">
      <h1>Posts</h1>
      <Outlet />
    </div>
  );
}

Loaders

Un loader est une fonction serveur qui fournit des données à une route avant son rendu. Il s’exécute côté serveur, ce qui lui permet de communiquer directement avec une base de données.

// app/routes/posts.$slug.tsx
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";

export async function loader({ params }: LoaderFunctionArgs) {
  const post = await getPost(params.slug);
  if (!post) throw json({ message: "Post not found" }, { status: 404 });
  return json({ post });
}

export default function Post() {
  const { post } = useLoaderData<typeof loader>();
  return <article>{post.title}</article>;
}

Il n’y a aucun état de chargement à gérer ni de requête côté client. Remix appelle le loader sur le serveur pour le rendu initial, puis à nouveau lors de la navigation, et le composant reçoit les données de manière synchrone.

Actions et formulaires

Les mutations sont gérées par des actions, qui sont des fonctions serveur liées à une route et déclenchées par la soumission de formulaires.

// app/routes/posts.new.tsx
import { redirect } from "@remix-run/node";
import { Form } from "@remix-run/react";

export async function action({ request }: ActionFunctionArgs) {
  const data = await request.formData();
  const title = String(data.get("title") ?? "").trim();

  if (!title) return json({ error: "Title is required" }, { status: 400 });

  await createPost(title);
  return redirect("/posts");
}

export default function NewPost() {
  return (
    <Form method="post">
      <input name="title" required />
      <button type="submit">Create</button>
    </Form>
  );
}

Comme il s’agit d’un véritable formulaire, celui-ci fonctionne sans JavaScript. Remix intercepte la soumission lorsque le client est prêt et revalide automatiquement les loaders concernés, afin que l’interface utilisateur reflète les nouvelles données sans mise à jour manuelle du cache.

Error boundaries

Chaque route peut exporter un ErrorBoundary qui capture les erreurs provenant de son loader, de son action ou de son composant.

// app/routes/posts.$slug.tsx
import { isRouteErrorResponse, useRouteError } from "@remix-run/react";

export function ErrorBoundary() {
  const error = useRouteError();

  if (isRouteErrorResponse(error) && error.status === 404) {
    return <h1>Post not found</h1>;
  }

  return <h1>Something went wrong</h1>;
}

Les boundaries sont imbriquées, donc une erreur dans une route enfant n’efface pas l’intégralité de la page. Le layout parent reste fonctionnel, ce qui offre une expérience bien meilleure qu’un écran blanc.

Routes de ressources et standards du web

Une route sans export par défaut est une resource route : elle renvoie des données plutôt qu’une interface utilisateur, ce qui est idéal pour les API et les webhooks.

// app/routes/api.health.tsx
export async function loader() {
  return json({ status: "ok", time: Date.now() });
}

Comme Remix utilise les Request et Response de la plateforme, vous pouvez lire les headers, définir des cookies, streamer des réponses et renvoyer n’importe quel code de statut sans avoir à apprendre une API spécifique au framework. Ces connaissances sont directement transférables à d’autres runtimes.

Pourquoi ce modèle semble différent

La plupart des applications React gèrent les données dans des effets et les conservent dans un état client, puis synchronisent cet état avec le serveur via des routes API. Remix fusionne ces couches :

  • La route possède ses données via un loader.
  • La route possède ses mutations via une action.
  • Le serveur détient la source de vérité, et le client reste léger.

Moins de pièces mobiles signifie moins de bugs, moins d’états à synchroniser et moins de code à écrire. Le compromis réside dans une vision plus tranchée sur la circulation des données, ce qui est précisément la raison pour laquelle les équipes qui l’adoptent ont tendance à l’apprécier.

Bonnes pratiques

  • Récupérez les données dans les loaders, et non dans les effects.
  • Effectuez les mutations via des actions et des formulaires, et laissez Remix gérer la revalidation.
  • Utilisez Form et Link de Remix pour que l’amélioration progressive fonctionne automatiquement.
  • Exportez un ErrorBoundary sur les routes susceptibles d’échouer.
  • Gardez vos routes imbriquées alignées avec la hiérarchie de l’interface utilisateur.
  • Utilisez des resource routes pour les API et les webhooks.
  • Renvoyez les codes de statut et les headers appropriés depuis les loaders et les actions.

Erreurs courantes

  • Effectuer des appels fetch dans useEffect au lieu d’un loader, entraînant la perte du rendu serveur.
  • Utiliser fetch pour les mutations au lieu d’une action et revalider les données manuellement.
  • Oublier le <Outlet /> dans une route de layout parente.
  • Intercepter les erreurs au lieu de laisser les boundaries les gérer.
  • Faire du sur-fetching dans un loader parent alors qu’une route enfant devrait posséder les données.
  • Traiter Remix comme une SPA côté client et lutter contre son modèle serveur.

Et après ?

Remix est l’expression la plus aboutie du concept “use the platform” dans l’univers React. Comparez-le avec Next.js pour découvrir l’autre approche majeure de React, et avec SvelteKit pour une philosophie similaire dans un autre écosystème. Renforcez vos bases en React, TypeScript et Node.js, puis créez une petite application comprenant un loader, une action et une error boundary.

Chargement de données

Un loader s'exécute sur le serveur avant le rendu de la route. Il n'y a pas d'état de chargement ni de requête client.

Préférer
export async function loader() {
  return json({
    posts: await getPosts(),
  });
}

export default function Posts() {
  const { posts } = useLoaderData();
  return <List items={posts} />;
}
Éviter
export default function Posts() {
  const [posts, setPosts] = useState([]);
  useEffect(() => {
    fetch("/api/posts")
      .then((r) => r.json())
      .then(setPosts);
  }, []);
  return <List items={posts} />;
}

Gestion des mutations

Une action gère le formulaire sur le serveur. Le même formulaire fonctionne avec ou sans JavaScript.

Préférer
export async function action({ request }) {
  const data = await request.formData();
  await createPost(data.get("title"));
  return redirect("/posts");
}

<Form method="post">
  <input name="title" />
  <button>Create</button>
</Form>
Éviter
async function onSubmit(e) {
  e.preventDefault();
  await fetch("/api/posts", {
    method: "POST",
    body: JSON.stringify(data),
  });
}

FAQ

Foire aux questions

Keep learning

Related topics from the roadmap.

$ commencer à apprendre

Prêt à apprendre Remix ?

Notre tutoriel interactif vous guide à travers Remix pas à pas — avec des quiz et du vrai code que vous pouvez exécuter dans le navigateur.