– Det er ikke server-side rendering.
Året 2020 har været en vanvittig tur for os alle sammen. Til denne juleafslutning har React-teamet for nylig annonceret spændende forskning i en ny måde at bygge React-apps på med React Server Components.
Hold venligst for øje, at React Server Components stadig er under udvikling og ikke anbefales til produktion endnu. Funktionen er helt valgfri, og du kan stadig skrive din komponent, som du gør i dag.
Du kan se det en time lange foredrag og demoen her, men her er en 5-minutters guide, der fremhæver og forklarer de vigtige dele.
Og hvis du er nysgerrig på, hvordan Reacts nye komponenter spiller en rolle i fremtidige designsystemer, anbefaler jeg, at du læser:
React Server Component er en måde at skrive React-komponent på, som bliver renderet på serversiden med det formål at forbedre React-apps ydeevne.
Et af de problemer, der opstår, når man udvikler applikationer med React, er det almindelige høje antal netværksanmodninger, der foretages, mens brugerne venter på, at den side/data, de har anmodet om, bliver tilgængelig:
Den almindelige tilgang til hentning af data i dag er f.eks. at kalde API’er ved hjælp af useEffect
hook:
useEffect(() => {
axios.get("URL HERE")
.then((response) => {
// set data into state setData(response.data);
})
.catch((error) => {
console.log(error);
});
}, );
Og selv om der ikke er noget galt med det, vil denne tilgang til hentning af data altid koste noget tid til at gengive noget meningsfuldt for brugeren.
Det andet problem er naturligvis bundlestørrelsen. Minificering, kodeopdeling, eliminering af død kode er nogle få eksempler på metoder, der bruges til at reducere bundle-størrelsen af React-applikationen. Hvorfor? Fordi en stor bundle-størrelse tager tid at downloade. Ikke alle har adgang til en hurtig enhed og hurtigt internet:
React Server Components vil hjælpe med at løse de to ovennævnte problemer og meget mere.
Hvordan React Server Components fungerer
Da React Server Components stadig befinder sig i den eksperimentelle fase, kan implementeringsdetaljerne for denne funktion ændre sig. Alligevel kan du få fat i nogle af dens kernekoncepter ved at kigge på demoen.
Den første ting at bemærke er, at der er flere pakker med en eksperimentel version i package.json
-filen:
"react": "0.0.0-experimental-3310209d0",
"react-dom": "0.0.0-experimental-3310209d0",
"react-fetch": "0.0.0-experimental-3310209d0",
"react-fs": "0.0.0-experimental-3310209d0",
"react-pg": "0.0.0-experimental-3310209d0",
"react-server-dom-webpack": "0.0.0-experimental-3310209d0",
Den react
, react-dom
og react-server-dom-webpack
bruger en eksperimentel version, der aktiverer React Server Component, mens react-fetch
, react-fs
og react-pg
er en gruppe af wrapper-pakker, der bruges til at interagere med input/output-systemet (De kaldes React IO Libraries)
Det næste punkt er, at denne demo er drevet af Express.js, hvilket giver mening, fordi du har brug for en server til at gengive komponenterne. Men det rejser også spørgsmålet: Betyder det, at Server Components kun fungerer i et JavaScript-miljø? Hvad med Go, Java og andre server-side-miljøer?
Det kan være, at vi vil se understøttelse af andre miljøer i fremtiden, så lad os se bort fra dette punkt for nu.
Selvfølgelig kan alle disse implementeringsdetaljer ændre sig i fremtiden, efterhånden som forskningen skrider frem.
Ved at gå til koden inde i src/
-mappen kan du se tre slags udvidelser for komponentfilerne:
-
.server.js
-udvidelsen angiver en Server Components -
.client.js
-udvidelsen angiver React Client Components - Den almindelige
.js
-udvidelse er for delte komponenter. Disse komponenter kan køres på serveren eller klienten, afhængigt af hvem der importerer dem.
Når du starter programmet med kommandoen npm start
, udføres to opgaver samtidig:
- Node-serveren, der kører ved hjælp af
server/api.server.js
-scriptet - Webpack-bygningen til React-bundlen på klientsiden ved hjælp af
scripts/build.js
-scriptet
Hvis du kigger på serverscriptet, kan du se, at app.server.js
bliver importeret i filen:
const ReactApp = require('../src/App.server').default;
og senere bliver behandlet som Node Writable stream:
const {pipeToNodeWritable} = require('react-server-dom-webpack/writer');async function renderReactTree(res, props) {
await waitForWebpack();
const manifest = readFileSync(
path.resolve(__dirname, '../build/react-client-manifest.json'),
'utf8'
);
const moduleMap = JSON.parse(manifest);
pipeToNodeWritable(React.createElement(ReactApp, props), res, moduleMap);
}
Koden under .server.js
-udvidelsen, herunder dens afhængigheder, er ikke inkluderet i klientbundlen, hvilket betyder, at den har nul effekt på bundlestørrelsen.
Serverkomponenter har direkte adgang til databasen eller filsystemet på serveren, så du kan hente alle de data, du har brug for, og sende dem til klienten ved den første rendering. Du kan se eksemplet i NoteList.server.js
filen:
export default function NoteList({searchText}) {const notes = db.query(
`select * from notes where title ilike order by id desc`,
).rows;
return notes.length > 0 ? (
<ul className="notes-list">
{notes.map((note) => (
<li key={note.id}>
<SidebarNote note={note} />
</li>
))}
</ul>
) : (
<div className="notes-empty">
{searchText
? `Couldn't find any notes titled "${searchText}".`
: 'No notes created yet!'}{' '}
</div>
);
}
Serverkomponenter kan ikke have nogen interaktivitet, hvilket betyder, at du ikke kan useState
eller oprette lyttere på serversiden. Du skal lægge tilstand i din klientside og importere dem fra serverkomponenterne.
Hvad er fordelen ved React Server Component?
- Serverkomponenterne er ikke inkluderet i bundlen. De downloades aldrig af browseren, hvilket har nul effekt på bundlestørrelsen
- Du kan reducere din bundlestørrelse ved at flytte statiske, renderingsbeskyttede komponenter til serversiden og beholde de interaktive, statelige komponenter på klientsiden
- Serverkomponenter kan få adgang til ressourcer på serversiden. Du kan hente data direkte fra databasen eller filsystemet, og du kan også hente fra API’er ligesom på klientsiden
- Serverkomponenter kan også læse GraphQL-forespørgsler
Hvordan er det forskelligt fra Server Side Rendering?
SSR, som det fungerer i dag i React-applikationer, er blot at sende komponenter renderet som HTML ind i klienten, så din app ser ud til at have et hurtigt svar. Brugeren kan intet gøre med din app, før JavaScript er downloadet.
React Server Components er anderledes. Som vist i demoen bliver Server Components ikke gengivet som HTML, men som et særligt format, der streames ind i klienten. Strømmen har ingen standardprotokol indtil videre, men den ligner meget JSON-formatet. Her er et stykke af svaret:
M1:{"id":"./src/SearchField.client.js","chunks":,"name":""}
Mens SSR kun bruges én gang til den indledende gengivelse, kan Server Components genhentes flere gange for at gengive dataene (i tilfældet med demoen, markdown-indlæggene).
Konklusion
React Server Components er en ny spændende funktion, der kan ændre den måde, som udviklere skriver deres React-applikation på. Den gør det muligt for React-applikationer at importere pakker uden at påvirke klientens bundle-størrelse, hvilket skaber en statisk repræsentation af applikationen, der kan gøres interaktiv ved hjælp af Client Components.
Udviklere kan også bruge både Server Components og Client Components under et enkelt DOM-træ, hvilket gør det muligt at hente serverkomponenter igen uden at ødelægge klientkomponenternes tilstand.
Men da denne funktion stadig er eksperimentel, er det svært at afgøre, hvordan den virkelig vil være nyttig i naturen. For det første kan denne funktion kun bruges under Node.js-servermiljøet i øjeblikket.
React-holdet fokuserer i øjeblikket på at bringe denne funktion ind i meta-frameworks som Next.js og Gatbsy, hvilket betyder, at der kan gå noget tid (hvis nogensinde), før vi ser understøttelse for andre serverside-sprog som PHP, Python, Go eller Ruby.
For at opsummere: Client-side React er ikke på vej væk. Server-side React er valgfrit.
Også har jeg delt mine tanker om Skal du oprette et designsystem for React Server Components? som måske vil interessere dig.