@bleedingdev/modern-js-main-doc 3.2.0-ultramodern.99 → 3.4.0-ultramodern.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/docs/en/apis/app/commands.mdx +59 -69
  2. package/docs/en/community/blog/v2-release-note.mdx +5 -5
  3. package/docs/en/community/blog/v3-release-note.mdx +1 -1
  4. package/docs/en/community/releases.mdx +1 -5
  5. package/docs/en/components/build-output.mdx +1 -1
  6. package/docs/en/components/debug-app.mdx +1 -1
  7. package/docs/en/components/deploy-command.mdx +3 -3
  8. package/docs/en/components/init-app.mdx +23 -51
  9. package/docs/en/components/prerequisites.mdx +1 -1
  10. package/docs/en/components/serve-command.mdx +3 -3
  11. package/docs/en/configure/app/bff/effect.mdx +27 -3
  12. package/docs/en/configure/app/performance/rsdoctor.mdx +7 -4
  13. package/docs/en/configure/app/tools/ts-checker.mdx +30 -2
  14. package/docs/en/configure/app/usage.mdx +6 -6
  15. package/docs/en/guides/advanced-features/bff/data-platform.mdx +3 -1
  16. package/docs/en/guides/advanced-features/bff/frameworks.mdx +3 -1
  17. package/docs/en/guides/advanced-features/international/api.mdx +1 -1
  18. package/docs/en/guides/advanced-features/international/configuration.mdx +1 -1
  19. package/docs/en/guides/advanced-features/international/locale-detection.mdx +1 -1
  20. package/docs/en/guides/advanced-features/international/routing.mdx +5 -3
  21. package/docs/en/guides/advanced-features/web-server.mdx +12 -0
  22. package/docs/en/guides/basic-features/debug/rsdoctor.mdx +2 -3
  23. package/docs/en/guides/basic-features/debug/using-storybook.mdx +1 -1
  24. package/docs/en/guides/basic-features/deploy.mdx +14 -14
  25. package/docs/en/guides/basic-features/env-vars.mdx +2 -2
  26. package/docs/en/guides/basic-features/render/_meta.json +1 -10
  27. package/docs/en/guides/basic-features/render/overview.mdx +0 -1
  28. package/docs/en/guides/basic-features/render/rsc.mdx +0 -1
  29. package/docs/en/guides/basic-features/routes/config-routes.mdx +2 -2
  30. package/docs/en/guides/basic-features/routes/routes.mdx +25 -10
  31. package/docs/en/guides/basic-features/testing/rstest.mdx +29 -0
  32. package/docs/en/guides/concept/server.mdx +2 -2
  33. package/docs/en/guides/get-started/quick-start.mdx +1 -1
  34. package/docs/en/guides/get-started/ultramodern.mdx +143 -26
  35. package/docs/en/guides/topic-detail/module-federation/application.mdx +1 -1
  36. package/docs/en/guides/topic-detail/module-federation/deploy.mdx +2 -2
  37. package/docs/en/guides/topic-detail/module-federation/usage.mdx +5 -5
  38. package/docs/en/guides/troubleshooting/builder.mdx +1 -1
  39. package/docs/en/guides/upgrade/config.mdx +1 -2
  40. package/docs/en/guides/upgrade/other.mdx +4 -4
  41. package/docs/zh/apis/app/commands.mdx +56 -66
  42. package/docs/zh/community/blog/v2-release-note.mdx +5 -5
  43. package/docs/zh/community/blog/v3-release-note.mdx +1 -1
  44. package/docs/zh/community/releases.mdx +1 -5
  45. package/docs/zh/components/build-output.mdx +1 -1
  46. package/docs/zh/components/debug-app.mdx +1 -1
  47. package/docs/zh/components/deploy-command.mdx +3 -3
  48. package/docs/zh/components/init-app.mdx +16 -47
  49. package/docs/zh/components/prerequisites.mdx +1 -1
  50. package/docs/zh/components/serve-command.mdx +3 -3
  51. package/docs/zh/configure/app/bff/effect.mdx +26 -2
  52. package/docs/zh/configure/app/performance/rsdoctor.mdx +7 -4
  53. package/docs/zh/configure/app/tools/ts-checker.mdx +30 -2
  54. package/docs/zh/configure/app/usage.mdx +6 -6
  55. package/docs/zh/guides/advanced-features/bff/data-platform.mdx +3 -1
  56. package/docs/zh/guides/advanced-features/bff/frameworks.mdx +3 -1
  57. package/docs/zh/guides/advanced-features/international/api.mdx +1 -1
  58. package/docs/zh/guides/advanced-features/international/configuration.mdx +1 -1
  59. package/docs/zh/guides/advanced-features/international/locale-detection.mdx +1 -1
  60. package/docs/zh/guides/advanced-features/international/routing.mdx +5 -3
  61. package/docs/zh/guides/advanced-features/web-server.mdx +12 -0
  62. package/docs/zh/guides/basic-features/debug/rsdoctor.mdx +2 -3
  63. package/docs/zh/guides/basic-features/debug/using-storybook.mdx +1 -1
  64. package/docs/zh/guides/basic-features/deploy.mdx +13 -13
  65. package/docs/zh/guides/basic-features/env-vars.mdx +2 -2
  66. package/docs/zh/guides/basic-features/render/_meta.json +1 -10
  67. package/docs/zh/guides/basic-features/render/overview.mdx +0 -1
  68. package/docs/zh/guides/basic-features/render/rsc.mdx +0 -1
  69. package/docs/zh/guides/basic-features/routes/config-routes.mdx +2 -2
  70. package/docs/zh/guides/basic-features/routes/routes.mdx +25 -10
  71. package/docs/zh/guides/basic-features/testing/rstest.mdx +29 -0
  72. package/docs/zh/guides/concept/server.mdx +2 -2
  73. package/docs/zh/guides/get-started/quick-start.mdx +1 -1
  74. package/docs/zh/guides/get-started/ultramodern.mdx +128 -22
  75. package/docs/zh/guides/topic-detail/module-federation/application.mdx +1 -1
  76. package/docs/zh/guides/topic-detail/module-federation/deploy.mdx +2 -2
  77. package/docs/zh/guides/topic-detail/module-federation/usage.mdx +5 -5
  78. package/docs/zh/guides/troubleshooting/builder.mdx +1 -1
  79. package/docs/zh/guides/upgrade/config.mdx +1 -2
  80. package/docs/zh/guides/upgrade/other.md +4 -4
  81. package/package.json +17 -14
  82. package/rspress.config.ts +17 -5
  83. package/src/components/Footer/index.tsx +3 -3
  84. package/src/components/Footer/styles.module.scss +1 -1
  85. package/src/components/Mermaid/style.scss +52 -52
  86. package/src/components/RandomMemberList/index.module.scss +8 -8
  87. package/src/components/SecondaryTitle/index.module.css +7 -2
  88. package/src/components/ShowcaseList/index.module.scss +1 -1
  89. package/src/components/ShowcaseList/useShowcases.ts +23 -65
  90. package/src/i18n/enUS.ts +0 -9
  91. package/src/i18n/zhCN.ts +0 -9
  92. package/src/pages/index.module.scss +6 -6
  93. package/src/sandbox/csr-auth/src/routes/page-tsx.txt +1 -1
  94. package/static/img/logo.svg +7 -0
  95. package/static/img/social-card.svg +12 -0
  96. package/builder-doc/docs/en/config/performance/rsdoctor.md +0 -37
  97. package/builder-doc/docs/zh/config/performance/rsdoctor.md +0 -37
  98. package/docs/en/guides/basic-features/render/tanstack-rsc.mdx +0 -226
  99. package/docs/zh/guides/basic-features/render/tanstack-rsc.mdx +0 -226
  100. package/main-doc/docs/en/guides/get-started/ultramodern.mdx +0 -403
  101. package/main-doc/docs/zh/guides/get-started/ultramodern.mdx +0 -363
@@ -1,226 +0,0 @@
1
- ---
2
- title: TanStack Router RSC
3
- ---
4
-
5
- # TanStack Router RSC
6
-
7
- Modern.js supports React Server Components (RSC) in TanStack Router projects by treating RSC output as router data. Loaders return serialized Flight streams, TanStack Router owns the data lifecycle, and Modern.js supplies the Flight renderer, decoder, and serialization adapter.
8
-
9
- This integration is designed for TanStack Router's data model. It does not use the React Router RSC renderer or `RSCStaticRouter`.
10
-
11
- ## When to Use It
12
-
13
- Use TanStack Router RSC when you want to:
14
-
15
- - Render data-heavy UI on the server while keeping TanStack Router as the routing and cache owner.
16
- - Return server-rendered UI from route loaders and consume it with `Route.useLoaderData()`.
17
- - Keep interactive UI in Client Components while expensive data access, formatting, and markup generation stay on the server.
18
- - Refresh server-rendered UI with TanStack Router invalidation after mutations.
19
-
20
- For route components that can be ordinary Server Components, use the general [React Server Components (RSC)](/guides/basic-features/render/rsc) guide first. Use this page when server UI needs to flow through TanStack Router loader data.
21
-
22
- ## Prerequisites
23
-
24
- Before using TanStack Router RSC, make sure the project has:
25
-
26
- 1. React and React DOM 19 or later.
27
- 2. RSC enabled with [`server.rsc`](/configure/app/server/rsc).
28
- 3. TanStack Router selected as the Modern.js routing runtime.
29
- 4. The base RSC setup from [React Server Components (RSC)](/guides/basic-features/render/rsc), including the required RSC runtime dependency.
30
-
31
- :::tip
32
- If your project was created with `--router tanstack`, use `@modern-js/plugin-tanstack/runtime` in route code. This keeps route code aligned with the TanStack plugin that generated it.
33
- :::
34
-
35
- ## Enable RSC
36
-
37
- Set `server.rsc` to `true` and enable the TanStack Router runtime:
38
-
39
- ```ts title="modern.config.ts"
40
- import { defineConfig } from '@modern-js/app-tools';
41
-
42
- export default defineConfig({
43
- runtime: {
44
- router: true,
45
- },
46
- server: {
47
- rsc: true,
48
- },
49
- });
50
- ```
51
-
52
- ## Import Paths
53
-
54
- Use the TanStack plugin runtime exports in application code:
55
-
56
- - Runtime APIs: `@modern-js/plugin-tanstack/runtime`
57
- - Server-only RSC helpers: `@modern-js/plugin-tanstack/runtime/rsc/server`
58
- - Client RSC helpers: `@modern-js/plugin-tanstack/runtime/rsc/client`
59
-
60
- The examples below use these paths.
61
-
62
- ## Payload Router Behavior
63
-
64
- When `server.rsc` is enabled, TanStack RSC navigation uses a native payload-router path instead of the React Router `RSCStaticRouter` path:
65
-
66
- - Browser navigations that need server loader data request the current URL with `x-rsc-tree: true`.
67
- - The server runs the matched TanStack route loaders, serializes a `ServerPayload` with matched route ids, params, loader data, errors, location, and route metadata, then streams that payload through the Modern.js RSC renderer.
68
- - Loader redirects are returned with `X-Modernjs-Redirect` and `X-Modernjs-BaseUrl` headers so the client can continue the navigation through TanStack Router.
69
- - `404` responses and TanStack `notFound()` results are preserved as route errors so the nearest TanStack not-found boundary can render.
70
- - Routes marked with a client loader keep running their client loader during RSC navigation. Their server loader data is intentionally omitted from the RSC payload to avoid hydrating stale server data over the client-loader result.
71
-
72
- Initial SSR hydration still uses TanStack Router's existing SSR bootstrap scripts. The payload-router request path is only used for subsequent RSC navigations and invalidations, so apps can mix ordinary TanStack SSR loader data and RSC loader data in the same route tree.
73
-
74
- ## Render Server UI From a Loader
75
-
76
- Use `renderServerComponent` when the server output does not need client-provided slots. The loader runs on the server, renders the Server Component to a Flight stream, and returns a value that can be rendered by the client route component.
77
-
78
- ```tsx title="src/routes/products/page.data.tsx"
79
- import { renderServerComponent } from '@modern-js/plugin-tanstack/runtime/rsc/server';
80
- import { ProductGrid } from './ProductGrid';
81
-
82
- export async function loader() {
83
- const products = await fetchProducts();
84
-
85
- return {
86
- ProductGrid: await renderServerComponent(
87
- <ProductGrid products={products} />,
88
- ),
89
- };
90
- }
91
- ```
92
-
93
- ```tsx title="src/routes/products/page.tsx"
94
- import { createFileRoute } from '@modern-js/plugin-tanstack/runtime';
95
-
96
- export const Route = createFileRoute('/products')({
97
- component: ProductsPage,
98
- });
99
-
100
- function ProductsPage() {
101
- const { ProductGrid } = Route.useLoaderData();
102
-
103
- return <main>{ProductGrid}</main>;
104
- }
105
- ```
106
-
107
- :::warning
108
- Do not return raw JSX from a TanStack Router loader when a client route will consume it. Wrap server-rendered UI with `renderServerComponent` or `createCompositeComponent` so the value can be serialized through TanStack Router's SSR data pipeline.
109
- :::
110
-
111
- ## Render Server UI With Client Slots
112
-
113
- Use `createCompositeComponent` when server-rendered markup must accept client content, render props, or interactive components. The server component receives slot placeholders, and the client route provides slot implementations through `<CompositeComponent>`.
114
-
115
- ```tsx title="src/routes/products/page.data.tsx"
116
- import { createCompositeComponent } from '@modern-js/plugin-tanstack/runtime/rsc/server';
117
- import type React from 'react';
118
-
119
- export async function loader() {
120
- return {
121
- ProductCard: await createCompositeComponent<{
122
- AddToCart?: (id: string) => React.ReactNode;
123
- children?: React.ReactNode;
124
- }>(async props => {
125
- const product = await fetchFeaturedProduct();
126
-
127
- return (
128
- <article>
129
- <h2>{product.name}</h2>
130
- {props.children}
131
- {props.AddToCart?.(product.id)}
132
- </article>
133
- );
134
- }),
135
- };
136
- }
137
- ```
138
-
139
- ```tsx title="src/routes/products/page.tsx"
140
- import {
141
- CompositeComponent,
142
- createFileRoute,
143
- } from '@modern-js/plugin-tanstack/runtime';
144
- import { AddToCartButton } from '../../components/AddToCartButton';
145
-
146
- export const Route = createFileRoute('/products')({
147
- component: ProductsPage,
148
- });
149
-
150
- function ProductsPage() {
151
- const { ProductCard } = Route.useLoaderData();
152
-
153
- return (
154
- <CompositeComponent
155
- src={ProductCard}
156
- AddToCart={id => <AddToCartButton productId={id} />}
157
- >
158
- <p>Ships today.</p>
159
- </CompositeComponent>
160
- );
161
- }
162
- ```
163
-
164
- Use `strict` when missing slot implementations should fail fast during development:
165
-
166
- ```tsx
167
- <CompositeComponent src={ProductCard} strict />
168
- ```
169
-
170
- ## Refreshing RSC Data
171
-
172
- Because RSC values are TanStack Router data, refresh them with TanStack Router invalidation:
173
-
174
- ```tsx
175
- import { useRouter } from '@modern-js/plugin-tanstack/runtime';
176
-
177
- function SaveButton() {
178
- const router = useRouter();
179
-
180
- return (
181
- <button
182
- onClick={async () => {
183
- await saveProduct();
184
- await router.invalidate();
185
- }}
186
- >
187
- Save
188
- </button>
189
- );
190
- }
191
- ```
192
-
193
- If you store RSC values in TanStack Query, disable structural sharing for that query. RSC values are proxies around Flight streams, so deep structural comparison is not meaningful for them.
194
-
195
- ## Notes
196
-
197
- - Server helpers from `*/rsc/server` must only be imported by server code such as loaders or server-only modules.
198
- - Client routes can render `renderServerComponent` output directly as React nodes.
199
- - Use `<CompositeComponent>` only for values returned by `createCompositeComponent`.
200
- - Slot functions should return React nodes and receive serializable arguments. Keep non-serializable objects, request objects, and database handles inside server code.
201
- - TanStack Router invalidation is the refresh boundary. Avoid building a separate RSC cache outside the router unless the application has a dedicated cache strategy.
202
-
203
- ## Best Practices
204
-
205
- ### Prefer Router Data Ownership
206
-
207
- Keep RSC values in loader data and let TanStack Router manage cache, hydration, invalidation, and navigation. This keeps the implementation aligned with TanStack Router and avoids a parallel RSC routing layer.
208
-
209
- ### Use the Smallest Helper That Fits
210
-
211
- Use `renderServerComponent` for slotless UI. Use `createCompositeComponent` only when server-rendered markup needs client slots or render props.
212
-
213
- ### Keep Server and Client Boundaries Clear
214
-
215
- Do not import server helpers into client components. Import `CompositeComponent` from the runtime export or from `*/rsc/client`, and import `renderServerComponent` / `createCompositeComponent` only from `*/rsc/server`.
216
-
217
- ### Automating Changes
218
-
219
- When using coding agents or codemods, keep TanStack RSC changes inside the TanStack Router plugin and its RSC helper exports. Do not modify Modern.js core routing or replace the TanStack Router SSR pipeline for this feature.
220
-
221
- ## Related Links
222
-
223
- - [React Server Components (RSC)](/guides/basic-features/render/rsc)
224
- - [Routing](/guides/basic-features/routes/routes)
225
- - [Data Cache](/guides/basic-features/data/data-cache)
226
- - [TanStack Router Documentation](https://tanstack.com/router)
@@ -1,226 +0,0 @@
1
- ---
2
- title: TanStack Router RSC
3
- ---
4
-
5
- # TanStack Router RSC
6
-
7
- Modern.js 支持在 TanStack Router 项目中使用 React Server Components(RSC)。这套集成会将 RSC 输出作为路由数据处理:Loader 返回序列化后的 Flight stream,由 TanStack Router 管理数据生命周期,Modern.js 负责提供 Flight 渲染、解码与序列化适配器。
8
-
9
- 这套集成遵循 TanStack Router 的数据模型,不会使用 React Router 的 RSC 渲染器或 `RSCStaticRouter`。
10
-
11
- ## 适用场景
12
-
13
- 当你希望实现以下能力时,可以使用 TanStack Router RSC:
14
-
15
- - 在服务端渲染数据密集型 UI,同时继续由 TanStack Router 管理路由与缓存。
16
- - 从路由 Loader 返回服务端渲染的 UI,并通过 `Route.useLoaderData()` 消费。
17
- - 将交互 UI 保留在 Client Component 中,将复杂的数据访问、格式化与标记生成放在服务端。
18
- - 在数据写入后,通过 TanStack Router 的 invalidation 刷新服务端渲染的 UI。
19
-
20
- 如果路由组件本身可以直接作为普通 Server Component 使用,请先阅读通用的 [React Server Components(RSC)](/guides/basic-features/render/rsc) 文档。当服务端 UI 需要通过 TanStack Router Loader 数据传递时,再使用本文介绍的能力。
21
-
22
- ## 前置条件
23
-
24
- 使用 TanStack Router RSC 前,请确保项目满足以下条件:
25
-
26
- 1. React 与 React DOM 已升级到 19 或更高版本。
27
- 2. 通过 [`server.rsc`](/configure/app/server/rsc) 开启 RSC。
28
- 3. 已选择 TanStack Router 作为 Modern.js 路由运行时。
29
- 4. 已完成 [React Server Components(RSC)](/guides/basic-features/render/rsc) 中的基础配置,包括必要的 RSC 运行时依赖。
30
-
31
- :::tip
32
- 如果项目通过 `--router tanstack` 创建,请在路由代码中使用 `@modern-js/plugin-tanstack/runtime`,这样可以让路由代码与生成它的 TanStack 插件保持一致。
33
- :::
34
-
35
- ## 开启 RSC
36
-
37
- 设置 `server.rsc` 为 `true`,并开启 TanStack Router 运行时:
38
-
39
- ```ts title="modern.config.ts"
40
- import { defineConfig } from '@modern-js/app-tools';
41
-
42
- export default defineConfig({
43
- runtime: {
44
- router: true,
45
- },
46
- server: {
47
- rsc: true,
48
- },
49
- });
50
- ```
51
-
52
- ## 导入路径
53
-
54
- 在应用代码中使用 TanStack 插件的运行时导出:
55
-
56
- - 运行时 API:`@modern-js/plugin-tanstack/runtime`
57
- - 仅服务端 RSC 辅助函数:`@modern-js/plugin-tanstack/runtime/rsc/server`
58
- - 客户端 RSC 辅助函数:`@modern-js/plugin-tanstack/runtime/rsc/client`
59
-
60
- 下面的示例都使用这些路径。
61
-
62
- ## Payload Router 行为
63
-
64
- 开启 `server.rsc` 后,TanStack RSC 导航会使用原生的 payload-router 路径,而不是 React Router 的 `RSCStaticRouter` 路径:
65
-
66
- - 需要服务端 Loader 数据的浏览器导航会携带 `x-rsc-tree: true` 请求当前 URL。
67
- - 服务端会执行匹配到的 TanStack 路由 Loader,并序列化包含匹配路由 id、params、loader data、errors、location 与路由元信息的 `ServerPayload`,再通过 Modern.js RSC renderer 以流式方式返回。
68
- - Loader 重定向会以 `X-Modernjs-Redirect` 与 `X-Modernjs-BaseUrl` 响应头返回,让客户端继续交给 TanStack Router 完成导航。
69
- - `404` 响应和 TanStack `notFound()` 结果会作为路由错误保留,从而渲染最近的 TanStack not-found boundary。
70
- - 标记了 client loader 的路由会在 RSC 导航期间继续执行自己的 client loader。对应的服务端 loader data 会从 RSC payload 中有意省略,避免用服务端数据覆盖 client-loader 结果。
71
-
72
- 首次 SSR hydration 仍然使用 TanStack Router 现有的 SSR bootstrap scripts。payload-router 请求路径只用于后续 RSC 导航和 invalidation,因此同一套路由树可以同时使用普通 TanStack SSR loader data 与 RSC loader data。
73
-
74
- ## 从 Loader 渲染服务端 UI
75
-
76
- 当服务端输出不需要客户端提供插槽时,使用 `renderServerComponent`。Loader 在服务端执行,将 Server Component 渲染成 Flight stream,并返回可以被客户端路由组件渲染的值。
77
-
78
- ```tsx title="src/routes/products/page.data.tsx"
79
- import { renderServerComponent } from '@modern-js/plugin-tanstack/runtime/rsc/server';
80
- import { ProductGrid } from './ProductGrid';
81
-
82
- export async function loader() {
83
- const products = await fetchProducts();
84
-
85
- return {
86
- ProductGrid: await renderServerComponent(
87
- <ProductGrid products={products} />,
88
- ),
89
- };
90
- }
91
- ```
92
-
93
- ```tsx title="src/routes/products/page.tsx"
94
- import { createFileRoute } from '@modern-js/plugin-tanstack/runtime';
95
-
96
- export const Route = createFileRoute('/products')({
97
- component: ProductsPage,
98
- });
99
-
100
- function ProductsPage() {
101
- const { ProductGrid } = Route.useLoaderData();
102
-
103
- return <main>{ProductGrid}</main>;
104
- }
105
- ```
106
-
107
- :::warning
108
- 当客户端路由会消费 Loader 返回值时,不要从 TanStack Router Loader 直接返回原始 JSX。请使用 `renderServerComponent` 或 `createCompositeComponent` 包装服务端渲染的 UI,使其能够通过 TanStack Router 的 SSR 数据管线序列化。
109
- :::
110
-
111
- ## 渲染带客户端插槽的服务端 UI
112
-
113
- 当服务端渲染的标记需要接收客户端内容、render props 或交互组件时,使用 `createCompositeComponent`。服务端组件会接收插槽占位符,客户端路由通过 `<CompositeComponent>` 提供插槽实现。
114
-
115
- ```tsx title="src/routes/products/page.data.tsx"
116
- import { createCompositeComponent } from '@modern-js/plugin-tanstack/runtime/rsc/server';
117
- import type React from 'react';
118
-
119
- export async function loader() {
120
- return {
121
- ProductCard: await createCompositeComponent<{
122
- AddToCart?: (id: string) => React.ReactNode;
123
- children?: React.ReactNode;
124
- }>(async props => {
125
- const product = await fetchFeaturedProduct();
126
-
127
- return (
128
- <article>
129
- <h2>{product.name}</h2>
130
- {props.children}
131
- {props.AddToCart?.(product.id)}
132
- </article>
133
- );
134
- }),
135
- };
136
- }
137
- ```
138
-
139
- ```tsx title="src/routes/products/page.tsx"
140
- import {
141
- CompositeComponent,
142
- createFileRoute,
143
- } from '@modern-js/plugin-tanstack/runtime';
144
- import { AddToCartButton } from '../../components/AddToCartButton';
145
-
146
- export const Route = createFileRoute('/products')({
147
- component: ProductsPage,
148
- });
149
-
150
- function ProductsPage() {
151
- const { ProductCard } = Route.useLoaderData();
152
-
153
- return (
154
- <CompositeComponent
155
- src={ProductCard}
156
- AddToCart={id => <AddToCartButton productId={id} />}
157
- >
158
- <p>Ships today.</p>
159
- </CompositeComponent>
160
- );
161
- }
162
- ```
163
-
164
- 如果希望缺失的插槽实现在开发阶段尽早报错,可以使用 `strict`:
165
-
166
- ```tsx
167
- <CompositeComponent src={ProductCard} strict />
168
- ```
169
-
170
- ## 刷新 RSC 数据
171
-
172
- 由于 RSC 值属于 TanStack Router 数据,应通过 TanStack Router invalidation 刷新:
173
-
174
- ```tsx
175
- import { useRouter } from '@modern-js/plugin-tanstack/runtime';
176
-
177
- function SaveButton() {
178
- const router = useRouter();
179
-
180
- return (
181
- <button
182
- onClick={async () => {
183
- await saveProduct();
184
- await router.invalidate();
185
- }}
186
- >
187
- Save
188
- </button>
189
- );
190
- }
191
- ```
192
-
193
- 如果将 RSC 值存入 TanStack Query,请为对应 query 关闭 structural sharing。RSC 值是 Flight stream 外层的代理对象,对其进行深度结构比较没有实际意义。
194
-
195
- ## 注意事项
196
-
197
- - `*/rsc/server` 中的服务端辅助函数只能被 Loader 或服务端模块导入。
198
- - 客户端路由可以将 `renderServerComponent` 的返回值直接作为 React node 渲染。
199
- - `<CompositeComponent>` 只应接收 `createCompositeComponent` 返回的值。
200
- - 插槽函数应返回 React node,并只接收可序列化参数。不可序列化对象、请求对象、数据库句柄等应保留在服务端代码中。
201
- - TanStack Router invalidation 是刷新边界。除非应用有明确的缓存策略,否则不要在 Router 之外再构建一套并行的 RSC 缓存。
202
-
203
- ## 最佳实践
204
-
205
- ### 优先由 Router 管理数据
206
-
207
- 将 RSC 值保存在 Loader 数据中,并让 TanStack Router 管理缓存、水合、失效与导航。这样可以保持实现与 TanStack Router 对齐,避免引入并行的 RSC 路由层。
208
-
209
- ### 使用能满足需求的最小辅助函数
210
-
211
- 没有客户端插槽的 UI 使用 `renderServerComponent`。只有当服务端渲染的标记需要客户端插槽或 render props 时,才使用 `createCompositeComponent`。
212
-
213
- ### 保持服务端与客户端边界清晰
214
-
215
- 不要在客户端组件中导入服务端辅助函数。`CompositeComponent` 应从运行时导出或 `*/rsc/client` 导入;`renderServerComponent` 与 `createCompositeComponent` 只应从 `*/rsc/server` 导入。
216
-
217
- ### 自动化修改
218
-
219
- 使用 coding agent 或 codemod 修改相关代码时,应将 TanStack RSC 的改动限制在 TanStack Router 插件及其 RSC 辅助导出内。不要为了该能力修改 Modern.js 核心路由,也不要替换 TanStack Router 的 SSR 管线。
220
-
221
- ## 相关链接
222
-
223
- - [React Server Components(RSC)](/guides/basic-features/render/rsc)
224
- - [路由基础](/guides/basic-features/routes/routes)
225
- - [数据缓存](/guides/basic-features/data/data-cache)
226
- - [TanStack Router 文档](https://tanstack.com/router)