Heim Web-Frontend js-Tutorial Erweiterte React SSR-Techniken mit Streaming und dynamischen Daten

Erweiterte React SSR-Techniken mit Streaming und dynamischen Daten

Jan 05, 2025 am 03:49 AM

Advanced React SSR Techniques with Streaming and Dynamic Data

Wenn Ihre Anwendung wächst, wachsen auch die Herausforderungen. Um an der Spitze zu bleiben, ist die Beherrschung fortschrittlicher SSR-Techniken für die Bereitstellung eines nahtlosen und leistungsstarken Benutzererlebnisses unerlässlich.

Nachdem ich im vorherigen Artikel eine Grundlage für serverseitiges Rendering in React-Projekten geschaffen habe, freue ich mich, Ihnen Funktionen vorstellen zu können, die Ihnen dabei helfen können, die Skalierbarkeit von Projekten aufrechtzuerhalten, Daten effizient vom Server auf den Client zu laden und Hydratationsprobleme zu lösen.

Inhaltsverzeichnis

  • Was ist Streaming in SSR?
  • Lazy Loading und SSR
  • Implementierung von Streaming mit Lazy Loading
    • React-Komponenten aktualisieren
    • Aktualisieren des Servers für Streaming
  • Server-zu-Client-Daten
    • Übergabe von Daten an den Server
    • Umgebungsvariablen auf dem Client verarbeiten
  • Probleme mit der Flüssigkeitszufuhr
    • Beispielszenario
    • Behebung von Flüssigkeitsproblemen
  • Fazit

Was ist Streaming in SSR?

Streaming beim serverseitigen Rendering (SSR) ist eine Technik, bei der der Server Teile der HTML-Seite in Blöcken an den Browser sendet, während sie generiert werden, anstatt darauf zu warten, dass die gesamte Seite fertig ist bevor Sie es ausliefern. Dadurch kann der Browser sofort mit dem Rendern von Inhalten beginnen, was die Ladezeiten und die Leistung des Benutzers verbessert.

Streaming ist besonders effektiv für:

  • Große Seiten: Das Generieren des gesamten HTML-Codes kann viel Zeit in Anspruch nehmen.
  • Dynamischer Inhalt: Wenn Teile der Seite von externen API-Aufrufen oder dynamisch generierten Blöcken abhängen.
  • Anwendungen mit hohem Datenverkehr: Zur Reduzierung der Serverlast und Latenz bei Spitzenauslastung.

Streaming schließt die Lücke zwischen traditionellem SSR und moderner clientseitiger Interaktivität und stellt sicher, dass Benutzer aussagekräftige Inhalte schneller sehen, ohne Kompromisse bei der Leistung einzugehen.

Lazy Loading und SSR

Lazy Loading ist eine Technik, die das Laden von Komponenten oder Modulen verzögert, bis sie tatsächlich benötigt werden, wodurch die anfängliche Ladezeit verkürzt und die Leistung verbessert wird. In Kombination mit SSR kann Lazy Loading sowohl die Server- als auch die Client-Arbeitslast erheblich optimieren.

Lazy Loading basiert auf React.lazy, das Komponenten dynamisch als Promises importiert. Im herkömmlichen SSR erfolgt das Rendering synchron, was bedeutet, dass der Server alle Promises auflösen muss, bevor er den vollständigen HTML-Code generiert und an den Browser sendet.

Streaming löst diese Herausforderungen, indem es dem Server ermöglicht, HTML in Blöcken zu senden, während Komponenten gerendert werden. Durch diesen Ansatz kann der Suspense-Fallback sofort an den Browser gesendet werden, sodass Benutzer frühzeitig aussagekräftige Inhalte sehen. Wenn verzögert geladene Komponenten aufgelöst werden, wird ihr gerenderter HTML-Code schrittweise an den Browser gestreamt und ersetzt so nahtlos den Fallback-Inhalt. Dadurch wird eine Blockierung des Rendering-Prozesses vermieden, Verzögerungen reduziert und die wahrgenommene Ladezeit verbessert.

Implementierung von Streaming mit Lazy Loading

Dieser Leitfaden baut auf Konzepten auf, die im vorherigen Artikel Erstellung produktionsbereiter SSR-React-Anwendungen vorgestellt wurden, den Sie unten verlinkt finden. Um SSR mit React zu ermöglichen und verzögert geladene Komponenten zu unterstützen, werden wir mehrere Updates sowohl an den React-Komponenten als auch am Server vornehmen.

Aktualisieren von Reaktionskomponenten

Server-Einstiegspunkt

Die renderToString-Methode von React wird üblicherweise für SSR verwendet, sie wartet jedoch, bis der gesamte HTML-Inhalt fertig ist, bevor sie ihn an den Browser sendet. Durch den Wechsel zu renderToPipeableStream können wir Streaming aktivieren, das Teile des HTML sendet, während sie generiert werden.

// ./src/entry-server.tsx
import { renderToPipeableStream, RenderToPipeableStreamOptions } from 'react-dom/server'
import App from './App'

export function render(options?: RenderToPipeableStreamOptions) {
  return renderToPipeableStream(<App />, options)
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Erstellen einer Lazy-Loaded-Komponente

In diesem Beispiel erstellen wir eine einfache Kartenkomponente, um das Konzept zu demonstrieren. In Produktionsanwendungen wird diese Technik typischerweise bei größeren Modulen oder ganzen Seiten verwendet, um die Leistung zu optimieren.

// ./src/Card.tsx
import { useState } from 'react'

function Card() {
  const [count, setCount] = useState(0)

  return (
    <div className="card">
      <button onClick={() => setCount((count) => count + 1)}>
        count is {count}
      </button>
      <p>
        Edit <code>src/App.tsx</code> and save to test HMR
      </p>
    </div>
  )
}

export default Card
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Verwenden der Lazy-Loaded-Komponente in der App

Um die Lazy-Loaded-Komponente zu verwenden, importieren Sie sie dynamisch mit React.lazy und umschließen Sie sie mit Suspense, um während des Ladens eine Fallback-Benutzeroberfläche bereitzustellen

// ./src/App.tsx
import { lazy, Suspense } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'

const Card = lazy(() => import('./Card'))

function App() {
  return (
    <>
      <div>
        <a href="https://vite.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <Suspense fallback='Loading...'>
        <Card />
      </Suspense>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
    </>
  )
}

export default App
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Aktualisieren des Servers für Streaming

Um Streaming zu ermöglichen, müssen sowohl die Entwicklungs- als auch die Produktionseinstellungen einen konsistenten HTML-Rendering-Prozess unterstützen. Da der Prozess für beide Umgebungen derselbe ist, können Sie eine einzige wiederverwendbare Funktion erstellen, um Streaming-Inhalte effektiv zu verarbeiten.

Erstellen einer Stream-Content-Funktion

// ./server/constants.ts
export const ABORT_DELAY = 5000
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Die streamContent-Funktion initiiert den Rendering-Prozess, schreibt inkrementelle HTML-Blöcke in die Antwort und stellt eine ordnungsgemäße Fehlerbehandlung sicher.

// ./server/streamContent.ts
import { Transform } from 'node:stream'
import { Request, Response, NextFunction } from 'express'
import { ABORT_DELAY, HTML_KEY } from './constants'
import type { render } from '../src/entry-server'

export type StreamContentArgs = {
  render: typeof render
  html: string
  req: Request
  res: Response
  next: NextFunction
}

export function streamContent({ render, html, res }: StreamContentArgs) {
  let renderFailed = false

  // Initiates the streaming process by calling the render function
  const { pipe, abort } = render({
    // Handles errors that occur before the shell is ready
    onShellError() {
      res.status(500).set({ 'Content-Type': 'text/html' }).send('<pre class="brush:php;toolbar:false">Something went wrong
') }, // Called when the shell (initial HTML) is ready for streaming onShellReady() { res.status(renderFailed ? 500 : 200).set({ 'Content-Type': 'text/html' }) // Split the HTML into two parts using the placeholder const [htmlStart, htmlEnd] = html.split(HTML_KEY) // Write the starting part of the HTML to the response res.write(htmlStart) // Create a transform stream to handle the chunks of HTML from the renderer const transformStream = new Transform({ transform(chunk, encoding, callback) { // Write each chunk to the response res.write(chunk, encoding) callback() }, }) // When the streaming is finished, write the closing part of the HTML transformStream.on('finish', () => { res.end(htmlEnd) }) // Pipe the render output through the transform stream pipe(transformStream) }, onError(error) { // Logs errors encountered during rendering renderFailed = true console.error((error as Error).stack) }, }) // Abort the rendering process after a delay to avoid hanging requests setTimeout(abort, ABORT_DELAY) }
Nach dem Login kopieren
Nach dem Login kopieren

Entwicklungskonfiguration aktualisieren

// ./server/dev.ts
import { Application } from 'express'
import fs from 'fs'
import path from 'path'
import { StreamContentArgs } from './streamContent'

const HTML_PATH = path.resolve(process.cwd(), 'index.html')
const ENTRY_SERVER_PATH = path.resolve(process.cwd(), 'src/entry-server.tsx')

// Add to args the streamContent callback
export async function setupDev(app: Application, streamContent: (args: StreamContentArgs) => void) {
  const vite = await (
    await import('vite')
  ).createServer({
    root: process.cwd(),
    server: { middlewareMode: true },
    appType: 'custom',
  })

  app.use(vite.middlewares)

  app.get('*', async (req, res, next) => {
    try {
      let html = fs.readFileSync(HTML_PATH, 'utf-8')
      html = await vite.transformIndexHtml(req.originalUrl, html)

      const { render } = await vite.ssrLoadModule(ENTRY_SERVER_PATH)

      // Use the same callback for production and development process
      streamContent({ render, html, req, res, next })
    } catch (e) {
      vite.ssrFixStacktrace(e as Error)
      console.error((e as Error).stack)
      next(e)
    }
  })
}
Nach dem Login kopieren
Nach dem Login kopieren

Aktualisierung der Produktionskonfiguration

// ./server/prod.ts
import { Application } from 'express'
import fs from 'fs'
import path from 'path'
import compression from 'compression'
import sirv from 'sirv'
import { StreamContentArgs } from './streamContent'

const CLIENT_PATH = path.resolve(process.cwd(), 'dist/client')
const HTML_PATH = path.resolve(process.cwd(), 'dist/client/index.html')
const ENTRY_SERVER_PATH = path.resolve(process.cwd(), 'dist/ssr/entry-server.js')

// Add to Args the streamContent callback
export async function setupProd(app: Application, streamContent: (args: StreamContentArgs) => void) {
  app.use(compression())
  app.use(sirv(CLIENT_PATH, { extensions: [] }))

  app.get('*', async (req, res, next) => {
    try {
      const html = fs.readFileSync(HTML_PATH, 'utf-8')

      const { render } = await import(ENTRY_SERVER_PATH)

      // Use the same callback for production and development process
      streamContent({ render, html, req, res, next })
    } catch (e) {
      console.error((e as Error).stack)
      next(e)
    }
  })
}
Nach dem Login kopieren

Aktualisieren des Express-Servers

Übergeben Sie die streamContent-Funktion an jede Konfiguration:

// ./server/app.ts
import express from 'express'
import { PROD, APP_PORT } from './constants'
import { setupProd } from './prod'
import { setupDev } from './dev'
import { streamContent } from './streamContent'

export async function createServer() {
  const app = express()

  if (PROD) {
    await setupProd(app, streamContent)
  } else {
    await setupDev(app, streamContent)
  }

  app.listen(APP_PORT, () => {
    console.log(`http://localhost:${APP_PORT}`)
  })
}

createServer()
Nach dem Login kopieren

Nach der Implementierung dieser Änderungen wird Ihr Server:

  • Streamen Sie HTML schrittweise an den Browser und verkürzen Sie so die Zeit bis zum ersten Malen.
  • Verarbeiten Sie nahtlos geladene Komponenten und verbessern Sie so sowohl die Leistung als auch das Benutzererlebnis.

Server-zu-Client-Daten

Bevor Sie HTML an den Client senden, haben Sie die volle Kontrolle über das vom Server generierte HTML. Dadurch können Sie die Struktur dynamisch ändern, indem Sie nach Bedarf Tags, Stile, Links oder andere Elemente hinzufügen.

Eine besonders wirkungsvolle Technik ist das Einfügen eines

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

<🎜>: Bubble Gum Simulator Infinity - So erhalten und verwenden Sie Royal Keys
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Fusionssystem, erklärt
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Flüstern des Hexenbaum
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

Java-Tutorial
1672
14
PHP-Tutorial
1276
29
C#-Tutorial
1256
24
Python vs. JavaScript: Die Lernkurve und Benutzerfreundlichkeit Python vs. JavaScript: Die Lernkurve und Benutzerfreundlichkeit Apr 16, 2025 am 12:12 AM

Python eignet sich besser für Anfänger mit einer reibungslosen Lernkurve und einer kurzen Syntax. JavaScript ist für die Front-End-Entwicklung mit einer steilen Lernkurve und einer flexiblen Syntax geeignet. 1. Python-Syntax ist intuitiv und für die Entwicklung von Datenwissenschaften und Back-End-Entwicklung geeignet. 2. JavaScript ist flexibel und in Front-End- und serverseitiger Programmierung weit verbreitet.

JavaScript und das Web: Kernfunktionalität und Anwendungsfälle JavaScript und das Web: Kernfunktionalität und Anwendungsfälle Apr 18, 2025 am 12:19 AM

Zu den Hauptanwendungen von JavaScript in der Webentwicklung gehören die Interaktion der Clients, die Formüberprüfung und die asynchrone Kommunikation. 1) Dynamisches Inhaltsaktualisierung und Benutzerinteraktion durch DOM -Operationen; 2) Die Kundenüberprüfung erfolgt vor dem Einreichung von Daten, um die Benutzererfahrung zu verbessern. 3) Die Aktualisierung der Kommunikation mit dem Server wird durch AJAX -Technologie erreicht.

JavaScript in Aktion: Beispiele und Projekte in realer Welt JavaScript in Aktion: Beispiele und Projekte in realer Welt Apr 19, 2025 am 12:13 AM

Die Anwendung von JavaScript in der realen Welt umfasst Front-End- und Back-End-Entwicklung. 1) Zeigen Sie Front-End-Anwendungen an, indem Sie eine TODO-Listanwendung erstellen, die DOM-Operationen und Ereignisverarbeitung umfasst. 2) Erstellen Sie RESTFUFFUPI über Node.js und express, um Back-End-Anwendungen zu demonstrieren.

Verständnis der JavaScript -Engine: Implementierungsdetails Verständnis der JavaScript -Engine: Implementierungsdetails Apr 17, 2025 am 12:05 AM

Es ist für Entwickler wichtig, zu verstehen, wie die JavaScript -Engine intern funktioniert, da sie effizientere Code schreibt und Leistungs Engpässe und Optimierungsstrategien verstehen kann. 1) Der Workflow der Engine umfasst drei Phasen: Parsen, Kompilieren und Ausführung; 2) Während des Ausführungsprozesses führt die Engine dynamische Optimierung durch, wie z. B. Inline -Cache und versteckte Klassen. 3) Zu Best Practices gehören die Vermeidung globaler Variablen, die Optimierung von Schleifen, die Verwendung von const und lass und die Vermeidung übermäßiger Verwendung von Schließungen.

Python gegen JavaScript: Community, Bibliotheken und Ressourcen Python gegen JavaScript: Community, Bibliotheken und Ressourcen Apr 15, 2025 am 12:16 AM

Python und JavaScript haben ihre eigenen Vor- und Nachteile in Bezug auf Gemeinschaft, Bibliotheken und Ressourcen. 1) Die Python-Community ist freundlich und für Anfänger geeignet, aber die Front-End-Entwicklungsressourcen sind nicht so reich wie JavaScript. 2) Python ist leistungsstark in Bibliotheken für Datenwissenschaft und maschinelles Lernen, während JavaScript in Bibliotheken und Front-End-Entwicklungsbibliotheken und Frameworks besser ist. 3) Beide haben reichhaltige Lernressourcen, aber Python eignet sich zum Beginn der offiziellen Dokumente, während JavaScript mit Mdnwebdocs besser ist. Die Wahl sollte auf Projektbedürfnissen und persönlichen Interessen beruhen.

Python vs. JavaScript: Entwicklungsumgebungen und Tools Python vs. JavaScript: Entwicklungsumgebungen und Tools Apr 26, 2025 am 12:09 AM

Sowohl Python als auch JavaScripts Entscheidungen in Entwicklungsumgebungen sind wichtig. 1) Die Entwicklungsumgebung von Python umfasst Pycharm, Jupyternotebook und Anaconda, die für Datenwissenschaft und schnelles Prototyping geeignet sind. 2) Die Entwicklungsumgebung von JavaScript umfasst Node.JS, VSCODE und WebPack, die für die Entwicklung von Front-End- und Back-End-Entwicklung geeignet sind. Durch die Auswahl der richtigen Tools nach den Projektbedürfnissen kann die Entwicklung der Entwicklung und die Erfolgsquote der Projekte verbessert werden.

Die Rolle von C/C bei JavaScript -Dolmetschern und Compilern Die Rolle von C/C bei JavaScript -Dolmetschern und Compilern Apr 20, 2025 am 12:01 AM

C und C spielen eine wichtige Rolle in der JavaScript -Engine, die hauptsächlich zur Implementierung von Dolmetschern und JIT -Compilern verwendet wird. 1) C wird verwendet, um JavaScript -Quellcode zu analysieren und einen abstrakten Syntaxbaum zu generieren. 2) C ist für die Generierung und Ausführung von Bytecode verantwortlich. 3) C implementiert den JIT-Compiler, optimiert und kompiliert Hot-Spot-Code zur Laufzeit und verbessert die Ausführungseffizienz von JavaScript erheblich.

Von Websites zu Apps: Die verschiedenen Anwendungen von JavaScript Von Websites zu Apps: Die verschiedenen Anwendungen von JavaScript Apr 22, 2025 am 12:02 AM

JavaScript wird in Websites, mobilen Anwendungen, Desktop-Anwendungen und serverseitigen Programmierungen häufig verwendet. 1) In der Website -Entwicklung betreibt JavaScript DOM zusammen mit HTML und CSS, um dynamische Effekte zu erzielen und Frameworks wie JQuery und React zu unterstützen. 2) Durch reaktnatives und ionisches JavaScript wird ein plattformübergreifendes mobile Anwendungen entwickelt. 3) Mit dem Elektronenframework können JavaScript Desktop -Anwendungen erstellen. 4) Node.js ermöglicht es JavaScript, auf der Serverseite auszuführen und unterstützt hohe gleichzeitige Anforderungen.

See all articles