Heim  >  Artikel  >  Web-Frontend  >  Serveraktionen wurden behoben

Serveraktionen wurden behoben

Linda Hamilton
Linda HamiltonOriginal
2024-10-21 06:22:02670Durchsuche

Serveraktionen entstanden als Idee, Client-Code zu reduzieren und die Interaktionen zu vereinfachen, die eine Kommunikation mit dem Server erfordern. Es ist eine hervorragende Lösung, die es Entwicklern ermöglicht, weniger Code zu schreiben. Allerdings sind mit der Implementierung in andere Frameworks einige Herausforderungen verbunden, die nicht übersehen werden sollten.

In diesem Artikel werden wir über diese Probleme sprechen und wie wir in Brisa eine Lösung gefunden haben.

Warum sind Serveraktionen erforderlich?

Um zu verstehen, was Serveraktionen bieten, ist es hilfreich, einen Blick darauf zu werfen, wie die Kommunikation mit dem Server früher war. Sie sind es wahrscheinlich gewohnt, bei jeder Interaktion mit dem Server die folgenden Aktionen auszuführen:

  1. Erfassen Sie ein Browserereignis (Client)
  2. Daten normalisieren und serialisieren (Client)
  3. Stellen Sie eine Anfrage an den Server (Client)
  4. Verarbeiten Sie die Anfrage in einer Endpunkt-API (Server)
  5. Antworten Sie mit den erforderlichen Daten (Server)
  6. Warten Sie auf die Antwort vom Server und verarbeiten Sie sie (Client)
  7. Aktualisieren Sie die Daten auf dem Client und rendern Sie die Änderungen (Client)

Diese sieben Aktionen werden bei jeder Interaktion wiederholt. Wenn Sie beispielsweise eine Seite mit 10 verschiedenen Interaktionen haben, wiederholen Sie einen sehr ähnlichen Code 10 Mal und ändern dabei nur Details wie die Art der Anfrage, die URL, die gesendeten Daten und den Status des Kunden.

Ein bekanntes Beispiel wäre
a:

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>

Und im Server:

app.post("/api/search", async (req, res) => {
  const { query } = req.body;
  const data = await search(query);
  res.json(data);
});

Erhöhung der Client-Bundle-Größe... und die Frustration der Entwickler.

Server Actions have been fixed


Frustrierter Entwickler

So funktionieren Serveraktionen

Serveraktionen kapseln diese Aktionen in einem Remote Procedure Call (RPC), der die Client-Server-Kommunikation verwaltet, den Code auf dem Client reduziert und die Logik auf dem Server zentralisiert :

  1. Erfassen Sie ein Browserereignis (RPC-Client)
  2. Daten normalisieren und serialisieren (RPC-Client)
  3. Stellen Sie eine Anfrage an den RPC-Server (RPC-Client)
  4. Führen Sie die Aktion auf dem Server mit den Daten (RPC-Server) aus
  5. Option 1:
  • Vom Server rendern und Streaming an den Client senden (RPC-Server)
  • Verarbeiten Sie die Teile des Streams, sodass die Änderungen sichtbar sind (RPC-Client)
  1. Option 2:
  • Antworten Sie mit den erforderlichen Daten und übertragen Sie Eigenschaften vom Serverspeicher zum Clientspeicher (RPC-Server)
  • Sorgen Sie dafür, dass die Signale, die auf die Änderungen lauschten, auf die Änderungen im Geschäft reagieren (RPC-Client)

Hier erledigt der Brisa RPC alles für Sie.

Server Actions have been fixed


Remote Procedure Call

Dies wäre der Code einer Serverkomponente:

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>

Hier schreiben Entwickler keinen Client-Code, da es sich um eine Serverkomponente handelt. Das onInput-Ereignis wird nach der Entprellung empfangen und vom Client-RPC verarbeitet, während der Server-RPC „Aktionssignale“ verwendet, um die Webkomponenten auszulösen, deren Signale bei dieser Store-Eigenschaft registriert sind.

Wie Sie sehen, wird dadurch der Servercode erheblich reduziert und das Beste ist, dass die Codegröße auf dem Client nicht mit jeder Interaktion zunimmt. Der RPC-Client-Code belegt eine feste Größe von 2 KB, unabhängig davon, ob Sie 10 oder 1000 solcher Interaktionen haben. Dies bedeutet, dass die Client-Bundle-Größe um 0 Bytes erhöht wird, mit anderen Worten: nicht erhöht wird.

Server Actions have been fixed


0 Bytes auf Client-Bundle-Größe

Wenn außerdem ein erneutes Rendern erforderlich ist, erfolgt dies auf dem Server und wird im HTML-Streaming zurückgegeben, sodass der Benutzer die Änderungen viel früher sieht als bei der herkömmlichen Methode, bei der Sie diese Arbeit anschließend auf dem Client durchführen mussten die Serverantwort.

Auf diese Weise:

  • Verbesserndie Benutzererfahrung (UX)
  • Verbesserndie Entwicklungserfahrung (DX)

Server Actions have been fixed


Glücklicher Entwickler

Unterschiede zwischen Brisa Server Actions und anderen Frameworks

1. Anzahl der zu erfassenden Ereignisse

In anderen Frameworks wie React haben sie sich darauf konzentriert, dass Aktionen nur Teil des Formulars bei Submit sind, und nicht eines Ereignisses.

Dies ist ein Problem, da es viele Nicht-Formularereignisse gibt, die auch von einer Serverkomponente aus verarbeitet werden sollten, ohne dass Clientcode hinzugefügt werden muss. Zum Beispiel ein onInput einer Eingabe, um automatische Vorschläge zu machen, ein onScroll zum Laden eines unendlichen Scrollens, ein onMouseOver um einen Hover usw. auszuführen

Server Actions have been fixed


Anwendungen sind interaktiver als erwartet

2. Mehr HTML-Steuerelemente für Serveraktionen

Viele Frameworks haben die HTMX-Bibliothek auch als eine ganz andere Alternative zu Serveraktionen gesehen, obwohl sie tatsächlich sehr gute Ideen hervorgebracht hat, die mit Serveraktionen kombiniert werden können, um mehr Potenzial zu haben, indem einfach zusätzliche Attribute im HTML hinzugefügt werden, die die Der RPC-Client kann beispielsweise den DebounceInput berücksichtigen, den wir zuvor gesehen haben. Auch andere HTMX-Ideen wie der Indikator, der beim Senden der Anfrage einen Spinner anzeigt, oder die Möglichkeit, einen Fehler im RPC-Client zu behandeln.

Server Actions have been fixed


HTMX-Ideen

3. Trennung der Anliegen

Als Serveraktionen in React eingeführt wurden, kam es zu einem neuen Paradigmenwechsel, bei dem viele Entwickler den mentalen Chip ändern mussten, wenn sie mit ihnen arbeiteten.

Wir wollten es der Webplattform so vertraut wie möglich machen, damit Sie das serialisierte Ereignis vom Server erfassen und seine Eigenschaften verwenden können. Das einzige Ereignis, das sich etwas unterscheidet, ist onSubmit, das die FormData bereits übertragen hat und über die Eigenschaft e.formData verfügt. Die übrigen Ereigniseigenschaften sind jedoch interaktiv. Dies ist ein Beispiel für das Zurücksetzen eines Formulars:

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>

In diesem Beispiel gibt es überhaupt keinen Client-Code und während der Serveraktion können Sie die Schaltfläche „Senden“ deaktivieren mit dem Indikator mithilfe von CSS, sodass das Formular nicht zweimal gesendet werden kann, und zwar gleichzeitig Zur gleichen Zeit, nachdem Sie die Aktion auf dem Server ausgeführt und auf die Formulardaten zugegriffen haben mit e.formData und dann das Formular zurückgesetzt haben unter Verwendung derselben API des Ereignisses.

Mental ist es der Arbeit mit der Webplattform sehr ähnlich. Der einzige Unterschied besteht darin, dass alle Ereignisse aller Serverkomponenten Serveraktionen sind.

Auf diese Weise gibt es eine echte Interessenstrennung, bei der es NICHT notwendig ist, "Benutzerserver" oder "Benutzerserver" in Ihr Konto einzufügen Komponenten mehr.

Denken Sie daran, dass alles nur auf dem Server läuft. Die einzige Ausnahme gilt für den Ordner src/web-components, der auf dem Client ausgeführt wird und dort sind die Ereignisse normal.

Server Actions have been fixed


Zwei verschiedene Welten, aber einig

4. Ereignisausbreitung

In Brisa werden die Serveraktionen zwischen Serverkomponenten weitergegeben, als wären sie DOM-Ereignisse. Das heißt, von einer Serveraktion aus können Sie ein Ereignis einer Requisite einer Serverkomponente aufrufen und dann wird die Serveraktion der übergeordneten Serverkomponente ausgeführt usw.

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>

In diesem Fall wird das Ereignis onAfterMyAction auf der übergeordneten Komponente ausgeführt und eine Aktion kann auf dem Server ausgeführt werden. Dies ist sehr nützlich, um Aktionen auf dem Server durchzuführen, die sich auf mehrere Serverkomponenten auswirken.

Server Actions have been fixed


Aktion verbreiten

4. Kommunikation zwischen beiden Welten

Besonders nach einigen Wochen waren Webkomponenten nach mehreren Diskussionen auf X (ehemals Twitter) etwas verpönt. Da es jedoch Teil des HTML ist, ist es aus mehreren Gründen die beste Möglichkeit, mit Serveraktionen zu interagieren:

  1. Sie können jedes Web Component-Ereignis vom Server erfassen und eine Client-Server-Kommunikation generieren. Beispiel . Dies ist sehr leistungsstark, da es sich bei allen Ereignissen innerhalb der Webkomponente nur um Client-Logik handelt, ohne dass dort Serverlogik eingefügt wird. Wenn Sie die Webkomponente nutzen, können Sie einfach vom Server aus Serveraktionen ausführen.
  2. Das HTTP-Protokoll kann für das verwendet werden, wofür es entwickelt wurde, nämlich zur Übertragung von Hypertext (HTML) im Streaming, auf diese Weise, wenn nach einem erneuten Beim Rendern aus einer Serveraktion wird jedes Attribut einer Webkomponente aktualisiert. Der Differenzierungsalgorithmus des RPC-Clients sorgt dafür, dass die Webkomponente ohne großen Aufwand aktualisiert wird. Die Web Components Attribute in Brisa sind Signale, die dafür sorgen, dass die internen Teile der Web Component reagieren, ohne dass ein erneutes Rendern erforderlich ist. Dieser Prozess wird in anderen Frameworks sehr kompliziert, sodass der RPC-Server JSON oder JS über das Kabel anstelle von HTML verarbeiten muss, was die Streaming-Implementierung komplizierter macht.

Die Verwendung von Attributen in Web Components erfordert eine Serialisierung auf die gleiche Weise wie die Übertragung von Daten vom Server zum Client ohne Verwendung von Web Components. Daher ist bei der Verwendung beider keine zusätzliche Serialisierung zu verwalten.

Hinweis: Das Streamen von HTML und dessen Verarbeitung mit dem Diffing-Algorithmus habe ich bei Interesse in diesem anderen Artikel erklärt.

Server Actions have been fixed


Hypertext beim Streaming über das Kabel

5. Neues Konzept: Aktionssignale

In Brisa haben wir ein neues Konzept hinzugefügt, um den Serveraktionen noch mehr Leistung zu verleihen. Dieses Konzept heißt „Aktionssignale“. Die Idee der „Aktionssignale“ besteht darin, dass Sie zwei Geschäfte haben, einen auf dem Server und einen auf dem Client.

Warum 2 Geschäfte?

Der standardmäßige Serverspeicher lebt nur auf der Anfrageebene. Und Sie können Daten weitergeben, die für den Kunden nicht sichtbar sind. Sie können beispielsweise festlegen, dass die Middleware den Benutzer festlegt und Zugriff auf vertrauliche Benutzerdaten in jeder Serverkomponente erhält. Durch das Leben auf Anfrageebene ist es unmöglich, Konflikte zwischen verschiedenen Anfragen zu haben, da jede Anfrage ihren eigenen Speicher hat und NICHT in einer Datenbank gespeichert ist, wenn die Wenn die Anfrage abgeschlossen ist, wird sie standardmäßig abgebrochen.

Andererseits handelt es sich im Kundenladen um einen Laden, bei dem jede Eigenschaft beim Konsum ein Signal ist, d. h. wenn Wenn es aktualisiert wird, reagiert die Webkomponente, die dieses Signal abgehört hat.

Das neue Konzept von „Action Signal“ besteht jedoch darin, dass wir die Lebensdauer des Serverspeichers über die Anforderung hinaus verlängern können. Dazu ist es notwendig, diesen Code zu verwenden:

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>

Diese transferToClient-Methode gibt Serverdaten an den Client-Speicher weiter und wandelt sie in Signale um. Auf diese Weise ist es in vielen Fällen nicht erforderlich, ein erneutes Rendern vom Server aus durchzuführen. Sie können einfach über eine Serveraktion die Signale der Webkomponenten reagieren lassen, die dieses Signal abgehört haben.

Diese Speicherübertragung verlängert die Lebensdauer des Serverspeichers jetzt:

Erste Serverkomponente rendern → Client → Serveraktion → Client → Serveraktion...

So geht es vom Leben nur auf Anforderungsebene zum dauerhaften Leben, kompatibel mit der Navigation zwischen Seiten.

Server Actions have been fixed


Daten zwischen beiden Welten (Server/Client) teilen

Beispiel:

app.post("/api/search", async (req, res) => {
  const { query } = req.body;
  const data = await search(query);
  res.json(data);
});

In diesem Beispiel verlängern wir die Lebensdauer der Fehlerspeichereigenschaft, nicht um sie auf dem Client zu verwenden, sondern um sie in der Serveraktion und schließlich beim erneuten Rendern der Serveraktion wiederzuverwenden. Da es sich in diesem Fall um nicht sensible Daten handelt, ist eine Verschlüsselung nicht erforderlich. Dieser Beispielcode erfolgt vollständig auf dem Server, sogar das erneute Rendern, und der Benutzer wird die Fehler nach diesem Rendern auf dem Server sehen, wo der Server-RPC die HTML-Blöcke im Streaming sendet und der Client-RPC sie verarbeitet, um den Unterschied zu machen und anzuzeigen Fehler, um dem Benutzer Feedback zu geben.

6. Verschlüsseln Sie nur die sensiblen Daten

Wenn innerhalb einer Serveraktion eine Variable verwendet wird, die auf Renderebene vorhanden war, verschlüsseln viele Frameworks wie Next.js 14 auf Sicherheitsebene diese Daten, um einen Snapshot der verwendeten Daten zu erstellen der Zeitpunkt der Darstellung. Das ist mehr oder weniger in Ordnung, aber Daten immer zu verschlüsseln ist mit Rechenaufwand verbunden und es handelt sich nicht immer um sensible Daten.

Um dieses Problem zu lösen, gibt es in Brisa verschiedene Anfragen, bei denen es beim ersten Rendern einen Wert hat und Sie in der Serveraktion den Wert erfassen können, den es in dieser Anfrage hat.

<input
  debounceInput={300}
  onInput={async (e) => {
    // All this code only runs on the server
    const data = await search(e.target.value);
    store.set("query", data);
    store.transferToClient(["query"]);
  }}
/>

Dies ist in einigen Fällen nützlich, aber nicht immer. Wenn Sie beispielsweise Math.random ausführen, wird es mit Sicherheit einen Unterschied zwischen dem ersten Rendering und der Ausführung der Serveraktion geben.

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>

Aus diesem Grund haben wir das Konzept von „Aktionssignalen“ entwickelt, um Daten vom Serverspeicher zum Clientspeicher und der Entwickler kann nach Belieben entscheiden, ob er verschlüsselt es verschlüsselt oder nicht.

Anstatt die Datenbank über die Serveraktion abzufragen, möchten Sie manchmal Daten übertragen, die bereits im ersten Rendering vorhanden sind, auch wenn hierfür eine zugehörige Verschlüsselung erforderlich ist. Dazu verwenden Sie einfach:

app.post("/api/search", async (req, res) => {
  const { query } = req.body;
  const data = await search(query);
  res.json(data);
});

Wenn Sie das tun:

<input
  debounceInput={300}
  onInput={async (e) => {
    // All this code only runs on the server
    const data = await search(e.target.value);
    store.set("query", data);
    store.transferToClient(["query"]);
  }}
/>

Innerhalb einer Webkomponente (Client) wird immer verschlüsselt, aber auf dem Server wird es immer entschlüsselt.

Hinweis: Brisa verwendet aes-256-cbc zur Verschlüsselung, eine Kombination kryptografischer Algorithmen zur sicheren Verschlüsselung von Informationen, die von OpenSSL empfohlen werden. Verschlüsselungsschlüssel werden während der Erstellung Ihres Projekts generiert.

Server Actions have been fixed


Verschlüsselte Daten zwischen beiden Welten (Server/Client) teilen

Abschluss

Obwohl wir in Brisa gerne das einfache Schreiben von Webkomponenten unterstützen, besteht das Ziel darin, eine SPA ohne Clientcode erstellen zu können und Webkomponenten nur dann zu verwenden, wenn es sich um eine reine Clientinteraktion handelt oder die Web-API berührt werden muss. Deshalb sind Serveraktionen so wichtig, da sie Interaktionen mit dem Server ermöglichen, ohne dass Client-Code geschrieben werden muss.

Wir empfehlen Ihnen, Brisa auszuprobieren. Sie müssen nur diesen Befehl im Terminal ausführen: bun create brisa, oder probieren Sie ein Beispiel aus, um zu sehen, wie es funktioniert.

Referenzen

  • Serveraktionskonvention
  • Serveraktionsverhalten
  • Formulare mit Serveraktionen
  • Verschachtelte Aktionen
  • Serverseitige Validierung und Fehlerbehandlung
  • Eine Serveraktion entprellen
  • Optimistische Updates
  • In Aktion erneut rendern
  • Navigieren Sie mit Serveraktionen zu einer anderen Seite
  • Zugriff auf Cookies
  • Sicherheit bei Serveraktionen
  • Aktionssignale
  • Sensible Daten übertragen
  • Requisiten in Serveraktionen
  • Serveraktionen in einem Reverse-Proxy verwenden

Das obige ist der detaillierte Inhalt vonServeraktionen wurden behoben. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn