react-vendoring

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

React Vendoring

React 内置依赖管理

Use this skill for changes touching vendored React,
react-server-dom-webpack/*
, or react-server layer boundaries.
当你需要修改内置 React、
react-server-dom-webpack/*
或 React Server 层边界相关代码时,请使用本技能文档。

App Router Vendoring

App Router 内置依赖管理

React is NOT resolved from
node_modules
for App Router. It's vendored into
packages/next/src/compiled/
during
pnpm build
(task:
copy_vendor_react()
in
taskfile.js
). Pages Router resolves React from
node_modules
normally.
  • Two channels: stable (
    compiled/react/
    ) and experimental (
    compiled/react-experimental/
    ). The runtime bundle webpack config aliases to the correct channel via
    makeAppAliases({ experimental })
    .
对于 App Router,React 并非从
node_modules
解析获取,而是在
pnpm build
过程中被内置到
packages/next/src/compiled/
目录中(对应 taskfile.js 中的
copy_vendor_react()
任务)。Pages Router 则正常从
node_modules
解析 React。
  • 两个渠道:稳定版(
    compiled/react/
    )和实验版(
    compiled/react-experimental/
    )。运行时打包的 webpack 配置会通过
    makeAppAliases({ experimental })
    别名到正确的渠道。

entry-base.ts
Boundary

entry-base.ts
边界规则

Only
entry-base.ts
is compiled in rspack's
(react-server)
layer. ALL imports from
react-server-dom-webpack/*
(Flight server/static APIs) must go through
entry-base.ts
. Other files like
stream-ops.node.ts
or
app-render.tsx
must access Flight APIs via the
ComponentMod
parameter (which is the
entry-base.ts
module exposed through the
app-page.ts
build template).
Direct imports from
react-server-dom-webpack/server.node
or
react-server-dom-webpack/static
in files outside
entry-base.ts
will fail at runtime with "The react-server condition must be enabled". Dev mode may mask this error, but production workers fail immediately.
只有
entry-base.ts
会在 rspack 的
(react-server)
层中编译。所有来自
react-server-dom-webpack/*
的导入(Flight 服务端/静态 API)必须通过
entry-base.ts
。其他文件如
stream-ops.node.ts
app-render.tsx
必须通过
ComponentMod
参数访问 Flight API(
ComponentMod
是通过
app-page.ts
构建模板暴露的
entry-base.ts
模块)。
entry-base.ts
之外的文件中直接导入
react-server-dom-webpack/server.node
react-server-dom-webpack/static
会在运行时失败,报错信息为"The react-server condition must be enabled"。开发模式可能会掩盖这个错误,但生产环境的 worker 会立即失败。

Type Declarations

类型声明

packages/next/types/$$compiled.internal.d.ts
contains
declare module
blocks for vendored React packages. When adding new APIs (e.g.
renderToPipeableStream
,
prerenderToNodeStream
), you must add type declarations here. The bare specifier types (e.g.
declare module 'react-server-dom-webpack/server'
) are what source code in
src/
imports against.
packages/next/types/$$compiled.internal.d.ts
包含内置 React 包的
declare module
块。当添加新的 API(如
renderToPipeableStream
prerenderToNodeStream
)时,你必须在此处添加类型声明。源码中导入的裸规范符类型(如
declare module 'react-server-dom-webpack/server'
)会被
src/
目录下的代码引用。

Adding Node.js-Only React APIs

添加仅 Node.js 可用的 React API

These exist in
.node
builds but not in the type definitions. Steps:
  1. Add type declarations to
    $$compiled.internal.d.ts
    .
  2. Export the API from
    entry-base.ts
    behind a
    process.env
    guard.
  3. Access it via
    ComponentMod
    in other files.
typescript
// In entry-base.ts (react-server layer) only:
/* eslint-disable import/no-extraneous-dependencies */
export let renderToPipeableStream: ... | undefined
if (process.env.__NEXT_USE_NODE_STREAMS) {
  renderToPipeableStream = (
    require('react-server-dom-webpack/server.node') as typeof import('react-server-dom-webpack/server.node')
  ).renderToPipeableStream
} else {
  renderToPipeableStream = undefined
}
/* eslint-enable import/no-extraneous-dependencies */

// In other files, access via ComponentMod:
ComponentMod.renderToPipeableStream!(payload, clientModules, opts)
这些 API 存在于
.node
构建版本中,但不在类型定义里。步骤如下:
  1. $$compiled.internal.d.ts
    中添加类型声明。
  2. entry-base.ts
    中通过
    process.env
    条件判断导出该 API。
  3. 在其他文件中通过
    ComponentMod
    访问该 API。
typescript
// In entry-base.ts (react-server layer) only:
/* eslint-disable import/no-extraneous-dependencies */
export let renderToPipeableStream: ... | undefined
if (process.env.__NEXT_USE_NODE_STREAMS) {
  renderToPipeableStream = (
    require('react-server-dom-webpack/server.node') as typeof import('react-server-dom-webpack/server.node')
  ).renderToPipeableStream
} else {
  renderToPipeableStream = undefined
}
/* eslint-enable import/no-extraneous-dependencies */

// In other files, access via ComponentMod:
ComponentMod.renderToPipeableStream!(payload, clientModules, opts)

ESLint Practical Rule

ESLint 实用规则

For guarded runtime
require()
blocks that need
import/no-extraneous-dependencies
suppression, prefer scoped block disable/enable. If using
eslint-disable-next-line
, the comment must be on the line immediately before the
require()
call, NOT before the
const
declaration. When the
const
and
require()
are on different lines, this is error-prone.
对于需要抑制
import/no-extraneous-dependencies
规则的受保护运行时
require()
代码块,优先使用作用域内的禁用/启用注释。如果使用
eslint-disable-next-line
,注释必须紧邻
require()
调用的上一行,而不是
const
声明的上一行。当
const
require()
不在同一行时,这一点容易出错。

Turbopack Remap

Turbopack 重映射

react-server-dom-webpack/*
is silently remapped to
react-server-dom-turbopack/*
by Turbopack's import map. Code says "webpack" everywhere, but Turbopack gets its own bindings at runtime. This affects debugging: stack traces and error messages will reference the turbopack variant.
Turbopack 的导入映射会自动将
react-server-dom-webpack/*
重映射到
react-server-dom-turbopack/*
。代码中到处都是“webpack”,但运行时 Turbopack 会使用自己的绑定。这会影响调试:堆栈跟踪和错误消息会引用 turbopack 变体。

Related Skills

相关技能

  • $flags
    - flag wiring (config/schema/define-env/runtime env)
  • $dce-edge
    - DCE-safe require patterns and edge constraints
  • $runtime-debug
    - reproduction and verification workflow
  • $flags
    - 标志配置(config/schema/define-env/运行时环境)
  • $dce-edge
    - 支持 DCE 的 require 模式和边缘约束
  • $runtime-debug
    - 复现与验证工作流