Qu'est-ce que les composants React Server?

Il y a à peine une semaine, l'équipe de réaction a publié sur son blog un article sur la nouvelle RFC . Voyons de quel type d'animal il s'agit et pourquoi il est nécessaire.






Qu'Est-ce que c'est

Comme son nom l'indique, les composants React Server sont des composants qui s'exécutent sur le serveur. Nous avons maintenant plusieurs types de composants:





  • Composants clients





  • Composants du serveur





  • Composants hybrides





Composants clients

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



Ainsi, lorsqu'un composant est exécuté sur le serveur, il peut interagir avec l'API nécessaire et transférer des données vers le composant en une itération sur le réseau pour l'utilisateur, après quoi le résultat de l'exécution du composant est transmis à l'utilisateur.





Résultat

À mon avis, les composants de serveur ont une place pour être, la combinaison de la suspension, du mode simultané et des composants de serveur peut être flexible pour les développeurs et facile à utiliser pour implémenter l'interface utilisateur.





N'oubliez pas cette RFC et l'approche, les implémentations et les API peuvent changer avant la publication officielle.





Que pensez-vous des composants serveur?





Matériels supplémentaires

Si vous souhaitez vous plonger plus en détail dans les composants du serveur.





Discours de Dan Abramov





Documentation RFC





Exemple d'application








All Articles