注册
web

Netflix 删除了 React ?

来源 Netflix Removed React?


Netflix 删除了 React


"Netflix 删除了 React,网站加载时间减少了 50%!"


这条爆炸性新闻在推特炸开了锅。这不禁让人想起半年前"微软应该禁止所有新项目使用 React" 的新闻 - 两大科技巨头相继 "抛弃" React,难道这预示着什么?


"React 心智负担重、性能差、bundle 体积大...". 一时间,各种唱衰 React 的声音此起彼伏。有人甚至信誓旦旦地表示:"只要像 Netflix 一样干掉 React,你的网站性能立马提升 50%!"


fake-twitter.png


这条发布于 2024 年 10 月 27 日的推文有着惊人的 150 万浏览量。但是,这大概率是 AI 生成的假新闻。
事实上,我们去 Netflix 的官网打开 react-devtools,发现他们依然在使用 React 构建他们的网站。


netflix-react-devtools.png


Netflix 的真实案例


这篇 AI 生成的假新闻灵感来自 2017 年 Netflix 工程师在 hack news 上发布的一篇文章 - Netflix: Removing client-side React.js improved performance by 50%


他直接移除了这篇文章最重要的部分 - client-side React.js, 也就是客户端的 React.js 代码。


实际的情况是,Netflix 团队在 2017 年的时候在使用 React 构建他们的 landing page


为什么在一个简单的 landing page 上要使用 React 呢?因为在 landing page



  • Netflix 需要处理大量的 AB 测试
  • 支持近 200 个国家的本地化
  • 根据用户设备、地理位置等因素动态调整内容
  • 需要服用现有的 React 组件

基于上述需求的考虑,Netflix 团队选择了使用 React 来构建他们的 landing page


为了优化页面加载性能,他们采用了服务端渲染的方案。同时,为了保证后续交互的流畅性,系统会预先加载(pre-fetch)后续流程所需的 React/Redux 相关代码。


从架构上看,这个 landing page 本质上仍然是一个单页面应用(SPA),保持了 SPA 快速响应的优势。不同之处在于首次访问时,页面内容是由服务端直接生成的,这样可以显著提升首屏加载速度。


这样做的缺点


显然,Netflix 在 2017 年这么做是有原因的,他们当时的确也没有更好的方案。在 2025 年的今天,
再来回顾这个方案,显然有以下缺点:


数据重复获取


在首屏渲染时,服务端需要获取数据来生成 HTML,而在客户端激活(hydration)后,为了保持交互性,往往又需要重新获取一遍相同的数据。
这种重复的数据获取不仅浪费资源,还可能带来不必要的性能开销。


客户端代码体积膨胀


因为本质上,Netflixlanding page 是一个还是一个 SPA,那么不可避免的,所有可能的 UI 状态都需要打包,
即使用户只需要其中的一部分代码。例如,在一个很常见的 tabs 页面


  <Tabs
defaultActiveKey="1"
items={[
{
label: 'Tab 1',
key: '1',
children: 'Tab 1',
},
{
label: 'Tab 2',
key: '2',
children: 'Tab 2',
disabled: true,
},
]}
/>

即使用户只点击了 Tab 1, 即使 Tab 2 没有被渲染,但是 Tab 2 的代码也会被打包。


如何解决这些问题


React Server Components (RSC) 为上述问题提供了优雅的解决方案:


避免数据重复获取


使用 RSC,组件可以直接在服务器端获取数据并渲染,客户端只接收最终的 HTML 结果。不再需要在客户端重新获取数据。


智能代码分割


RSC 允许我们选择性地决定哪些组件在服务器端运行,哪些在客户端运行。例如:


function TabContent({ tab }: { tab: string }) {
// 这部分代码只在服务器端运行,不会打包到客户端
return <div>{tab} 内容</div>
}

// 客户端组件
'use client'
function TabWrapper({ children }) {
const [activeTab, setActiveTab] = useState('1')
return (
<div>
{/* Tab 切换逻辑 */}
{children}
</div>

)
}

在这个例子中:



  • TabContent 的所有可能状态都在服务器端预渲染
  • 只有实际需要交互的 TabWrapper 会发送到客户端
  • 用户获得了更小的 bundle 体积和更快的加载速度

这不就是 PHP?


经常会看到有人说:"Server Components 不就是重新发明了 PHP 吗?都是在服务端生成 HTML。"


显然,PHP 与现在的 Server Components 在开发体验上有本质的区别。


1. 细粒度的服务端-客户端混合


与 PHP 不同,RSC 允许我们在组件级别决定渲染位置,用一个购物车的例子来说明:


// 服务端组件
function ProductDetails({ id }: { id: string }) {
// 在服务器端获取数据和渲染
const product = await db.products.get(id);
return <div>{product.name}</div>;
}

// 客户端组件
'use client'
function AddToCart({ productId }: { productId: string }) {
// 在客户端处理交互
return <button onClick={() => addToCart(productId)}>加入购物车</button>;
}

// 混合使用
function ProductCard({ id }: { id: string }) {
return (
<div>
<ProductDetails id={id} />
<AddToCart productId={id} />
</div>

);
}

这种设计充分利用了服务端和客户端各自的优势 - 在服务端可以直接访问数据库获取 ProductDetails 所需的数据,而在客户端则能更好地处理 AddToCart 这样的用户交互。这不仅提升了性能,也让代码结构更加清晰合理。


2. 保持组件的可复用性


RSC 最强大的特性之一是组件的可复用性不受渲染位置的影响:


// 这个组件可以在服务端渲染
function UserProfile({ id }: { id: string }) {
return <ProfileCard id={id} />;
}

// 同样的组件也可以在客户端动态加载
'use client'
function UserList() {
const [selectedId, setSelectedId] = useState(null);
return selectedId ? <ProfileCard id={selectedId} /> : null;
}

因为都是 React 组件,区别仅仅是渲染位置的不同,同一个组件可以:



  • 在服务端预渲染时使用
  • 在客户端动态加载时使用
  • 在流式渲染中使用

这种统一的组件模型是 PHP 等传统服务端渲染所不具备的。


3. 智能的序列化


RSC 还提供了智能的序列化机制,可以自动将组件的 propsstate 序列化,从而在服务端和客户端之间传递。
避免了重复获取数据的问题。


// 服务端组件
async function Comments({ postId }: { postId: string }) {
// 1. 获取评论数据
const comments = await db.comments.list(postId);

// 2. 传递给客户端组件
return <CommentList initialComments={comments} />;
}

// 客户端组件
'use client'
function CommentList({ initialComments }) {
// 3. 直接使用服务端数据,无需重新请求
const [comments, setComments] = useState(initialComments);

return (
// 渲染评论列表
);
}

4. 渐进式增强


RSC 还提供了渐进式增强的能力,可以在服务端和客户端之间无缝过渡。



  • 首次访问时返回完整的 HTML
  • 按需加载客户端交互代码
  • 保持应用的可访问性

这让我们能够构建既有良好首屏体验,又能提供丰富交互的现代应用,完美解决了在 2017 年 Netflix 所提出的问题。


总结


通过对上面这些案例的分析,我们可以看出


1. 不要轻信网络传言


网络上充斥着各种技术传言。虽然像上面这种完全虚构的假新闻容易识破,但有些传言会巧妙地利用真实数据和案例,通过夸张的描述来误导技术选型和决策,这类信息需要我们格外谨慎分辨。
例如:



svelte 放弃 TypeScript 改用 JSdoc 进行类型检查



这个确实是一个真的新闻,但是并不代表着 Typescript 的没落,实际上



  • Svelte 团队选择 JSDoc 是为了减少编译时间
  • 这是针对框架源码的优化,而不是面向使用者的建议
  • Svelte 依然完整支持 TypeScript,用户代码可以继续使用 .ts/.ts


tauri 打包后的体积比 electron 小多了,我们应该放弃 electron 使用 tauri



技术选型不能仅仅看单一指标。虽然 tauri 的打包体积确实小于 electron,但在开发体验、性能、稳定性、生态和社区支持等关键维度上都存在明显短板。


如果你尝试用 tauri 开发复杂应用,很可能会因为生态不完善、社区支持不足而陷入困境。当你遇到问题去 GitHub 寻找解决方案时,看到许多库已经一年未更新,就会明白为什么大多数团队仍在选择 electron


2. 历史的选择


2017 年的 Netflix 面临着复杂的业务需求,他们选择了当时最佳的解决方案 - 服务端渲染 + 客户端激活。这个方案虽然解决了问题,但也带来了一些困扰:



  • 数据需要在服务端和客户端重复获取
  • JavaScript bundle 体积过大

3. RSC 带来的改变


React Server Components 为这些历史遗留问题带来了全新的解决思路:



  • 服务端渲染与客户端渲染完美融合
  • 智能的代码分割,最小化客户端 bundle 体积
  • 数据获取更高效,避免重复请求
  • 渐进式增强,提供流畅的用户体验

4. 技术演进的启示


Netflix 2017 年的实践到今天的 RSC,我们可以看到:



  • 技术方案在不断进化,过去的最佳实践可能已不再适用
  • RSC 不是简单的"回归服务端",而是开创了全新的开发模式
  • 性能与开发体验不再是非此即彼的选择

RSC 代表了现代前端开发的新趋势 - 既保持了 React 强大的组件化能力,又通过创新的架构设计解决了历史难题。这让我们终于可以在性能和开发体验之间找到完美平衡。


作者:snow分享
来源:juejin.cn/post/7459029441039794211

0 个评论

要回复文章请先登录注册