Loading...
Loading...
Compare original and translation side by side
'use client''use server''use client''use server'Update (React 19 / modern frameworks): React Server Components are now a production feature for framework users. Unlike classic SSR, RSCs let you render part of your UI on the server without shipping that component's JavaScript to the client. The Container/Presentational pattern is a strong fit here: the "container" can be a Server Component that fetches data and passes it to an interactive Client Component.In Next.js App Router, you no longer use—instead, any React component in thegetServerSidePropsdirectory can be async to fetch data on the server. React Server Components are not a replacement for SSR—they complement it. You typically use RSC for the majority of the page (rendered and streamed as part of SSR), and addapp/directives for components that need interactivity.'use client'Thedirective is for Server Functions or Server Actions, not for marking a component as a Server Component. Server Components have no directive; they are the default in frameworks that support them unless you opt into'use server'.'use client'
更新(React 19 / 现代框架): React Server Components现已成为框架用户可用的生产级功能。与传统SSR不同,RSCs允许你在服务端渲染部分UI,而无需将该组件的JavaScript发送到客户端。容器/展示模式非常适合这种场景:“容器”可以是一个Server Component,负责获取数据并将其传递给交互式的Client Component。在Next.js App Router中,你不再需要使用——相反,getServerSideProps目录下的任何React组件都可以是异步的,以在服务端获取数据。React Server Components不是SSR的替代品,而是其补充。通常,页面的大部分内容使用RSC渲染(作为SSR的一部分进行流式传输),并为需要交互性的组件添加app/指令。'use client'指令用于标记Server Functions或Server Actions,而非将组件标记为Server Component。Server Component无需指令;在支持它的框架中,除非你选择使用'use server',否则默认就是Server Component。'use client'
[RFC]: Developers constantly have to make choices about using third-party packages. Using a package to render some markdown or format a date is convenient for us as developers, but it increases code size and hurts performance for our users
// *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 */);
}[RFC原文]:开发者经常需要权衡是否使用第三方包。使用包来渲染markdown或格式化日期对开发者来说很方便,但会增加代码体积并影响用户体验
// *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 */);
}[RFC]: If we migrate the above example to a Server Component we can use the exact same code for our feature but avoid sending it to the client - a code savings of over 240K (uncompressed):
import marked from "marked"; // zero bundle size
import sanitizeHtml from "sanitize-html"; // zero bundle size
function NoteWithMarkdown({text}) {
// same as before
}[RFC原文]:如果我们将上述示例迁移到Server Component,我们可以使用完全相同的代码实现功能,但无需将其发送到客户端——节省了超过240K的未压缩代码:
import marked from "marked"; // zero bundle size
import sanitizeHtml from "sanitize-html"; // zero bundle size
function NoteWithMarkdown({text}) {
// same as before
}React.lazy()// *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 <PhotoRenderer {...props} />;
}
}importimport 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 <PhotoRenderer {...props} />;
}
}React.lazy()// *Before* Server Components
import React from "react";
// 其中一个会在客户端渲染时开始加载:
const OldPhotoRenderer = React.lazy(() => import("./OldPhotoRenderer.js"));
const NewPhotoRenderer = React.lazy(() => import("./NewPhotoRenderer.js"));
function Photo(props) {
// 根据功能标志、登录状态、内容类型等切换:
if (FeatureFlags.useNewPhotoRenderer) {
return <NewPhotoRenderer {...props} />;
} else {
return <PhotoRenderer {...props} />;
}
}importimport React from "react";
// 其中一个会在渲染并流式传输到客户端后开始加载:
import OldPhotoRenderer from "./OldPhotoRenderer.client.js";
import NewPhotoRenderer from "./NewPhotoRenderer.client.js";
function Photo(props) {
// 根据功能标志、登录状态、内容类型等切换:
if (FeatureFlags.useNewPhotoRenderer) {
return <NewPhotoRenderer {...props} />;
} else {
return <PhotoRenderer {...props} />;
}
}getServerSideProps()getServerSideProps()