Web Standards Framework

Remix

Remix ist das React-Framework, das Web-Standards an erste Stelle setzt. Es setzt auf HTTP, Formulare und Progressive Enhancement, sodass Ihre App bereits funktioniert, bevor das JavaScript geladen ist.

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>;
}
Basiert auf
React
Modell
Nested routes
Daten
loaders
Mutationen
actions
Philosophie
Web standards first
Aktueller Stand
Integriert in React Router v7

Warum es wichtig ist

Warum Remix einen anderen Weg geht

Progressive Enhancement

Formulare und Navigation funktionieren ohne JavaScript und werden schneller und flüssiger, sobald es geladen ist.

Nested Routes mit Daten

Jede Route lädt ihre eigenen Daten und behandelt ihre eigenen Fehler, parallel zu ihren Geschwister-Routes.

Weniger bewegliche Teile

Loader und Actions ersetzen das übliche Gewirr aus Client-State, Effects und API-Aufrufen.

Das Gesamtbild

Die drei Grundideen hinter Remix

Routes besitzen ihre eigenen Daten, Mutationen sind Formulare und alles funktioniert ohne JavaScript stabil weiter.

Routes

Struktur

Nested Routes definieren die URL, das Layout und die Datengrenze an einem einzigen Ort.

Loader und Actions

Daten

Server-Funktionen, die Daten vor dem Rendering lesen und Mutationen aus Formularen verarbeiten.

Web-Standards

Fundament

Requests, Responses, Formulare und Header sind Plattform-Primitive, keine Framework-Abstraktionen.

Remix auf einen Blick

Der Kern von Remix

Nested Routes

Route-Module werden verschachtelt, um der UI-Hierarchie zu entsprechen und Daten parallel zu laden.

Loader

Server-Funktionen, die einer Route Daten bereitstellen, bevor sie gerendert wird.

Actions

Server-Funktionen, die Formular-Submissions und Mutationen verarbeiten.

Formulare

Echte HTML-Formulare, die ohne JavaScript funktionieren und automatisch optimiert werden.

Error Boundaries

Route-spezifische Fehlerbehandlung, die den Rest der Seite funktionsfähig hält.

Resource Routes

Routes, die Daten statt einer UI zurückgeben, nützlich für APIs und Webhooks.

Eine kurze Geschichte

Vom Remix des Webs zu React Router

  1. 2020

    Remix angekündigt

    Die Schöpfer von React Router stellen ein Framework vor, das auf Web-Standards basiert.

    20
  2. 2021

    Open Source

    Remix wird öffentlich veröffentlicht und erregt Aufmerksamkeit durch sein Datenlademodell.

    21
  3. 2022

    Remix 1.0 und Shopify

    Ein stabiler Release erfolgt, und Shopify übernimmt das Team und führt Remix ein.

    22
  4. 2024

    React Router v7

    Die Ideen von Remix werden in React Router integriert, und Remix wird zum Framework-Modus davon.

    24
  5. Heute

    Standards-first React

    Das Modell lebt als Framework-Modus von React Router mit derselben Philosophie weiter.

    Heute

Der vollständige Leitfaden

Remix: Alles was Sie wissen müssen

Was ist Remix?

Remix ist ein React framework, das auf Webstandards aufbaut. Während viele Frameworks die Plattform abstrahieren, setzt Remix voll darauf: HTTP requests und responses, HTML forms, links, header und cookies bilden das Fundament, und das Framework erweitert diese, anstatt sie zu ersetzen.

Das Ergebnis ist eine Anwendung, die bereits funktioniert, bevor JavaScript geladen ist. Formulare werden abgeschickt, links navigieren und Daten erscheinen, weil der Server die Arbeit erledigt. Sobald JavaScript geladen ist, werden dieselben Interaktionen augenblicklich und partiell. Diese Eigenschaft nennt man progressive enhancement, und sie ist die zentrale Idee von Remix.

Im Jahr 2024 hat das Remix-Team das Framework in React Router v7 integriert, wo es nun als Framework-Modus existiert. Die Konzepte und APIs sind unverändert, sodass alle hier beschriebenen Informationen für beides gelten.

Verschachtelte Routen

Routen sind Dateien unter app/routes, wobei Punkte in Dateinamen den URL-Segmenten entsprechen.

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

Routen werden verschachtelt, um der UI zu entsprechen. Eine Eltern-Route rendert ein gemeinsames Layout und ein <Outlet />, und die Kind-Routen werden darin gerendert. Da Remix den gesamten Routen-Baum kennt, kann es die Daten für eine Seite und alle ihre verschachtelten Routen parallel laden, anstatt in einem Waterfall.

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

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

Loader

Ein loader ist eine Server-Funktion, die einer Route Daten bereitstellt, bevor diese gerendert wird. Da er auf dem Server ausgeführt wird, kann er direkt mit einer Datenbank kommunizieren.

// 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>;
}

Es muss kein Ladezustand verwaltet werden und es gibt keine clientseitigen Requests. Remix ruft den loader auf dem Server für das initiale Rendering sowie bei der Navigation auf, und die Komponente erhält die Daten synchron.

Actions und Formulare

Mutationen werden durch actions gehandhabt. Dabei handelt es sich um Server-Funktionen, die an eine Route gebunden sind und durch das Absenden von Formularen ausgelöst werden.

// 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>
  );
}

Da es sich hierbei um ein echtes Formular handelt, funktioniert es auch ohne JavaScript. Remix fängt das Absenden ab, sobald der Client bereit ist, und validiert die betroffenen loader automatisch neu. So spiegelt die UI die neuen Daten wider, ohne dass manuelle Cache-Updates erforderlich sind.

Error Boundaries

Jede Route kann eine ErrorBoundary exportieren, die Fehler aus ihrem Loader, ihrer Action oder ihrer Komponente abfängt.

// 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>;
}

Boundaries sind verschachtelt, sodass ein Fehler in einer Child-Route nicht die gesamte Seite leert. Das umschließende Layout bleibt funktionsfähig, was eine wesentlich bessere User Experience ist als ein weißer Bildschirm.

Ressourcen-Routes und Webstandards

Eine Route ohne Default-Export ist eine Ressourcen-Route: Sie gibt Daten anstelle einer UI zurück, was ideal für APIs und Webhooks ist.

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

Da Remix die Request und Response der Plattform nutzt, können Sie Header auslesen, Cookies setzen, Antworten streamen und beliebige Statuscodes zurückgeben, ohne eine framework-spezifische API erlernen zu müssen. Dieses Wissen lässt sich direkt auf andere Runtimes übertragen.

Warum sich das Modell anders anfühlt

Die meisten React-Apps verwalten Daten in Effects und speichern sie im Client-State, um diesen Zustand anschließend über API-Routes wieder mit dem Server zu synchronisieren. Remix bricht diese Ebenen auf:

  • Die Route besitzt ihre Daten über einen loader.
  • Die Route besitzt ihre Mutationen über eine action.
  • Der Server besitzt die “Source of Truth”, während der Client schlank bleibt.

Weniger bewegliche Teile bedeuten weniger Bugs, weniger zu synchronisierender State und weniger zu schreibender Code. Der Kompromiss ist eine striktere Meinung darüber, wie Daten fließen – und genau das ist der Grund, warum Teams, die Remix einsetzen, es meist sehr schätzen.

Best Practices

  • Daten in Loadern abrufen, nicht in Effects.
  • Mutationen über Actions und Forms durchführen und die Revalidierung durch Remix übernehmen lassen.
  • Form und Link von Remix verwenden, damit das Enhancement automatisch funktioniert.
  • Auf Routen, die fehlschlagen können, eine ErrorBoundary exportieren.
  • Verschachtelte Routen an der UI-Hierarchie ausrichten.
  • Resource Routes für APIs und Webhooks nutzen.
  • Korrekte Statuscodes und Header aus Loadern und Actions zurückgeben.

Häufige Fehler

  • Fetching in useEffect anstatt in einem loader, wodurch das Server-Rendering verloren geht.
  • Verwendung von fetch für Mutationen anstatt einer action und die manuelle Revalidierung der Daten.
  • Das Vergessen von <Outlet /> in einer übergeordneten Layout-Route.
  • Das Verschlucken von Fehlern, anstatt sie von Boundaries handhaben zu lassen.
  • Over-fetching in einem Parent-Loader, obwohl eine Child-Route die Daten besitzen sollte.
  • Remix wie eine clientseitige SPA zu behandeln und gegen dessen Server-Modell zu arbeiten.

Wie geht es weiter?

Remix ist die konsequenteste Umsetzung des „use the platform“-Ansatzes in der React-Welt. Vergleiche es mit Next.js, um den anderen großen React-Ansatz kennenzulernen, und mit SvelteKit für eine ähnliche Philosophie in einem anderen Ökosystem. Vertiefe deine Grundlagen in React, TypeScript und Node.js und baue anschließend eine kleine App mit einem loader, einer action und einer error boundary.

Daten laden

Ein Loader läuft auf dem Server, bevor die Route gerendert wird. Es gibt keinen Loading-State und keinen Client-Request.

Bevorzugt
export async function loader() {
  return json({
    posts: await getPosts(),
  });
}

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

Mutationen verarbeiten

Eine Action verarbeitet das Formular auf dem Server. Dasselbe Formular funktioniert mit oder ohne JavaScript.

Bevorzugt
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>
Vermeiden
async function onSubmit(e) {
  e.preventDefault();
  await fetch("/api/posts", {
    method: "POST",
    body: JSON.stringify(data),
  });
}

Häufig gestellte Fragen

Häufig gestellte Fragen

Keep learning

Related topics from the roadmap.

$ Lernen Sie jetzt

Bereit, Remix zu lernen?

Unser interaktives Tutorial führt Sie Schritt für Schritt durch Remix — mit Quizzen und echtem Code, den Sie im Browser ausführen können.