React Server Components重新定义服务端渲染前言各位前端小伙伴不知道你们有没有遇到过这种情况页面加载时需要等待大量JavaScript下载和执行导致首屏渲染缓慢我曾经开发过一个内容网站首屏加载时间超过5秒。后来我引入了React Server Components首屏加载时间降到了1秒以内什么是Server ComponentsReact Server ComponentsRSC是React团队推出的一种新的组件类型它允许组件在服务器端运行只将渲染结果发送到客户端从而减少客户端JavaScript体积提升首屏加载性能。Server Components工作原理┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ 服务器端 │ │ 网络 │ │ 客户端 │ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ │ │ │ 1. 渲染Server Component│ │ │───────────────────────│ │ │ │ │ │ │ 2. 发送渲染结果(JSON)│ │ │────────────────────────│ │ │ │ │ │ │ 3. 客户端渲染 │ │ │ │─────────────│创建Server Components基本结构// ServerComponent.js async function ServerComponent() { const data await fetchData() return ( div {data.map((item) ( Item key{item.id} item{item} / ))} /div ) } export default ServerComponent客户端组件引用// ClientComponent.js use client import { useState } from react function ClientComponent({ initialValue }) { const [count, setCount] useState(initialValue) return ( div divCount: {count}/div button onClick{() setCount(c c 1)}Increment/button /div ) } export default ClientComponentServer Components vs Client Components特性Server ComponentsClient Components运行位置服务器端客户端状态管理不支持useState/useEffect支持所有hooks数据获取可以直接调用数据库需要通过API获取文件大小不发送到客户端发送到客户端交互性无有在Next.js中使用Server Components页面组件// app/page.js async function HomePage() { const posts await fetchPosts() return ( div h1Welcome to my blog/h1 PostList posts{posts} / /div ) } export default HomePage布局组件// app/layout.js async function RootLayout({ children }) { const user await getUser() return ( html head titleMy App/title /head body Header user{user} / {children} /body /html ) } export default RootLayoutServer Components实战数据获取// app/posts/page.js async function PostsPage() { const posts await fetch(https://api.example.com/posts).then(res res.json()) return ( div h1Posts/h1 ul {posts.map((post) ( li key{post.id} h2{post.title}/h2 p{post.excerpt}/p /li ))} /ul /div ) } export default PostsPage嵌套使用// app/blog/page.js async function BlogPage() { const posts await getPosts() return ( div h1Blog/h1 PostList posts{posts} / /div ) } async function PostList({ posts }) { return ( div {posts.map((post) ( PostCard key{post.id} post{post} / ))} /div ) } async function PostCard({ post }) { const author await getAuthor(post.authorId) return ( div h3{post.title}/h3 pBy {author.name}/p /div ) }混合使用Server和Client Components在Server Component中使用Client Component// app/page.js import ClientCounter from ./ClientCounter async function HomePage() { const initialCount await getInitialCount() return ( div h1Home/h1 ClientCounter initialCount{initialCount} / /div ) } export default HomePage // app/ClientCounter.js use client import { useState } from react function ClientCounter({ initialCount }) { const [count, setCount] useState(initialCount) return ( div divCount: {count}/div button onClick{() setCount(c c 1)}Increment/button /div ) } export default ClientCounter在Client Component中使用Server Component// app/ClientWrapper.js use client import { useState } from react import ServerContent from ./ServerContent function ClientWrapper() { const [isLoaded, setIsLoaded] useState(false) return ( div {isLoaded ? ( ServerContent / ) : ( divLoading.../div )} button onClick{() setIsLoaded(true)}Load Content/button /div ) } export default ClientWrapperServer Components最佳实践1. 将数据获取逻辑放在Server Components中async function ProductList() { const products await fetchProducts() return ( div {products.map((product) ( ProductCard key{product.id} product{product} / ))} /div ) }2. 将交互逻辑放在Client Components中use client function ProductCard({ product }) { const [isFavorite, setIsFavorite] useState(false) return ( div h3{product.name}/h3 button onClick{() setIsFavorite(!isFavorite)} {isFavorite ? ❤️ : } /button /div ) }3. 合理划分组件边界// Server Component - 数据获取 async function BlogPost({ id }) { const post await getPost(id) return ( article h1{post.title}/h1 ContentRenderer content{post.content} / CommentSection postId{id} / /article ) } // Client Component - 交互 use client function CommentSection({ postId }) { const [comments, setComments] useState([]) useEffect(() { fetchComments(postId).then(setComments) }, [postId]) return ( div {comments.map((comment) ( Comment key{comment.id} comment{comment} / ))} /div ) }常见问题问题1Server Component中无法使用hooks解决方案将需要hooks的逻辑移到Client Component中问题2Client Component无法直接获取数据解决方案通过props从Server Component传递数据问题3缓存问题解决方案使用revalidate属性控制缓存策略export const revalidate 60 // 60秒重新验证Server Components的优势减少JavaScript体积Server Components不发送到客户端提升首屏加载服务端渲染更快的首屏展示简化数据获取直接在组件中获取数据更好的SEO完整的HTML输出总结React Server Components是React生态的重要革新。通过使用Server Components我们可以优化性能减少客户端JavaScript体积提升体验更快的首屏加载简化开发直接在组件中获取数据改进SEO完整的服务端渲染现在开始使用Server Components构建更高效的应用吧你的用户会感谢你的最后一句忠告不要将所有组件都改为Server Components根据需求合理选择