276 - 《手撕源码 30:wakuwork 和 RSC 原理》

发布于 2023年3月21日

手撕 wakuwork 之前,我们先理解下 React Server Components,下面简称为 RSC 。

我们以一个具体例子来看 RSC 的实现。比如有两个文件,app.tsx 和 foo.tsx,其中 foo.tsx 加了 "use client" 的标记,所以 app.tsx 应该在 server 端渲染,foo.tsx 应该在 client 端渲染。

import { Foo } from './foo';
export function App() {
  return <><h1>App</h1><Foo /></>
}
"use client";
export function Foo() {
  return <div>Foo</div>;
}

1、当用户访问应用时,需要通知 server 渲染 App 组件,拿到 App 组件的流式数据后拼成 React 组件需要的数据格式,最终渲染到页面里。

import ReactDOM from 'react-dom/client';
import { createFromFetch } from 'react-server-dom-webpack/client';
// 从 server 拿 App 组件的数据
// rsc 表示 react server components
const response = fetch('/?rsc_id=App&props=...');
const options = {};
// 基于 response 创建 React 组件
const data = await createFromFetch(response, options);
// 渲染组件到页面
ReactDOM.createRoot(document.getElementById('root')).render(data);

2、server 在处理 /?rsc_id=App&props=… 时做了什么?又返回了什么数据?

node-register 的实现见 react/ReactFlightWebpackNodeRegister.js,针对 "use client""use server" 分别处理,返回额外的 id、typeof、bound 等元信息。

// 注册 node register,处理 "use client" 和 "use server"
const RSDWRegister = require('react-server-dom-webpack/node-register');
RSDWRegister();

const bundleConfig = new Proxy({}, {
  get(target, id) {
    const [filePath, name] = id.split("#");
    return {
      id, chunks: 

内容预览已结束

此内容需要会员权限。请先登录以查看完整内容。