Was sind React Server-Komponenten?

Erst vor einer Woche hat das Reaktionsteam in seinem Blog über den neuen RFC gepostet . Lassen Sie uns herausfinden, um welche Art von Tier es sich handelt und warum es benötigt wird.






Was ist das

Wie der Name schon sagt, sind React Server-Komponenten Komponenten, die auf dem Server ausgeführt werden. Wir haben jetzt verschiedene Arten von Komponenten:





  • Client-Komponenten





  • Serverkomponenten





  • Hybridkomponenten





Client-Komponenten

, , . . .client.js







, ( useState



"" ). . . .server.js



. , .





. . . JSX .





SSR

, SSR



Next.js



. , ? . , SSR



HTML



, . SSR



, . Server Components JSON



virtual dom



.





, , server components.





SSR server components, .





, . , .





, , .server.js







// Note.server.js - Server Component

import db from 'db.server'; 
// (A1) We import from NoteEditor.client.js - a Client Component.
import NoteEditor from 'NoteEditor.client';

function Note(props) {
  const {id, isEditing} = props;
  // (B) Can directly access server data sources during render, e.g. databases
  const note = db.posts.get(id);

  return (
    <div>
      <h1>{note.title}</h1>
      <section>{note.body}</section>
      {/* (A2) Dynamically render the editor only if necessary */}
      {isEditing 
        ? <NoteEditor note={note} />
        : null
      }
    </div>
  );
}
      
      



.





, , :





Zero-Bundle-Size Components

, , . , , . , markdown , :





// NoteWithMarkdown.js
// NOTE: *before* Server Components

import marked from 'marked'; // 35.9K (11.2K gzipped)
import sanitizeHtml from 'sanitize-html'; // 206K (63.3K gzipped)

function NoteWithMarkdown({text}) {
  const html = sanitizeHtml(marked(text));
  return (/* render */);
}
      
      



bundle 74 , server components, :





// NoteWithMarkdown.server.js - Server Component === zero bundle size

import marked from 'marked'; // zero bundle size
import sanitizeHtml from 'sanitize-html'; // zero bundle size

function NoteWithMarkdown({text}) {
  const html = sanitizeHtml(marked(text));
  return (/* render */);
}
      
      



, 74 .





Backend

, :





// Note.server.js - Server Component
import fs from 'react-fs';

function Note({id}) {
  const note = JSON.parse(fs.readFile(`${id}.json`));
  return <NoteWithMarkdown note={note} />;
}
      
      



// Note.server.js - Server Component
import db from 'db.server';

function Note({id}) {
  const note = db.notes.get(id);
  return <NoteWithMarkdown note={note} />;
}
      
      



, , 3 :





  • react-fs



    -





  • react-fetch



    -





  • react-pg



    - PostgresSql





, API server component.





Code Splitting

, Code Splitting. , , bundle React.lazy:





// PhotoRenderer.js
// NOTE: *before* Server Components

import React from 'react';

// one of these will start loading *when rendered on the client*:
const OldPhotoRenderer = React.lazy(() => import('./OldPhotoRenderer.js'));
const NewPhotoRenderer = React.lazy(() => import('./NewPhotoRenderer.js'));

function Photo(props) {
  // Switch on feature flags, logged in/out, type of content, etc:
  if (FeatureFlags.useNewPhotoRenderer) {
    return <NewPhotoRenderer {...props} />; 
  } else {
    return <OldPhotoRenderer {...props} />;
  }
}
      
      



Server Components, :





// PhotoRenderer.server.js - Server Component

import React from 'react';

// one of these will start loading *once rendered and streamed to the client*:
import OldPhotoRenderer from './OldPhotoRenderer.client.js';
import NewPhotoRenderer from './NewPhotoRenderer.client.js';

function Photo(props) {
  // Switch on feature flags, logged in/out, type of content, etc:
  if (FeatureFlags.useNewPhotoRenderer) {
    return <NewPhotoRenderer {...props} />;
  } else {
    return <OldPhotoRenderer {...props} />;
  }
}
      
      



, , .





client-server

- , , , .





. , API. graphql/JSON API .





:





// Note.js
// NOTE: *before* Server Components

function Note(props) {
  const [note, setNote] = useState(null);
  useEffect(() => {
    // NOTE: loads *after* rendering, triggering waterfalls in children
    fetchNote(props.id).then(noteData => {
      setNote(noteData);
    });
  }, [props.id]);
  if (note == null) {
    return "Loading";
  } else {
    return (/* render note here... */);
  }
}
      
      



Note, . server components , :





// Note.server.js - Server Component

function Note(props) {
  // NOTE: loads *during* render, w low-latency data access on the server
  const note = db.notes.get(props.id);
  if (note == null) {
    // handle missing note
  }
  return (/* render note here... */);
}
      
      



Wenn eine Komponente auf dem Server ausgeführt wird, kann sie mit der erforderlichen API interagieren und Daten in einer Iteration über das Netzwerk für den Benutzer an die Komponente übertragen. Anschließend wird das Ergebnis der Ausführung der Komponente an den Benutzer gestreamt





Ergebnis

Meiner Meinung nach haben Serverkomponenten einen Platz, an dem die Kombination von Suspend, Concurent Mode und Server Components für Entwickler flexibel und benutzerfreundlich sein kann, um die Benutzeroberfläche zu implementieren.





Vergessen Sie diesen RFC und Ansatz nicht. Implementierungen und APIs können sich vor der offiziellen Veröffentlichung ändern.





Was halten Sie von Serverkomponenten?





Zusätzliches Material

Wenn Sie detaillierter auf Serverkomponenten eingehen möchten.





Dan Abramovs Rede





RFC-Dokumentation





Beispielanwendung








All Articles