@modern-js/main-doc 2.58.2 → 2.59.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (140) hide show
  1. package/docs/en/apis/app/runtime/core/use-loader.mdx +1 -1
  2. package/docs/en/community/blog/_meta.json +1 -6
  3. package/docs/en/components/deploy.mdx +1 -1
  4. package/docs/en/components/init-app.mdx +0 -1
  5. package/docs/en/components/init-rspack-app.mdx +0 -1
  6. package/docs/en/components/ssr-monitor.mdx +3 -0
  7. package/docs/en/configure/_meta.json +1 -1
  8. package/docs/en/configure/app/output/ssg.mdx +52 -141
  9. package/docs/en/configure/app/tools/swc.mdx +1 -1
  10. package/docs/en/configure/app/tools/tailwindcss.mdx +1 -1
  11. package/docs/en/guides/advanced-features/_meta.json +0 -8
  12. package/docs/en/guides/advanced-features/bff/_meta.json +1 -6
  13. package/docs/en/guides/advanced-features/rsbuild-plugin.mdx +2 -2
  14. package/docs/en/guides/advanced-features/rspack-start.mdx +7 -22
  15. package/docs/en/guides/basic-features/_meta.json +31 -9
  16. package/docs/en/guides/basic-features/css/_meta.json +1 -0
  17. package/docs/en/guides/basic-features/css/css-in-js.mdx +34 -0
  18. package/docs/en/guides/basic-features/{css-modules.mdx → css/css-modules.mdx} +0 -4
  19. package/docs/en/guides/basic-features/css/css.mdx +25 -0
  20. package/docs/en/guides/basic-features/{css.mdx → css/tailwindcss.mdx} +5 -66
  21. package/docs/en/guides/basic-features/data/_meta.json +1 -4
  22. package/docs/en/guides/basic-features/data/data-fetch.mdx +134 -235
  23. package/docs/en/guides/basic-features/data/data-write.mdx +66 -77
  24. package/docs/en/guides/basic-features/debug/_meta.json +1 -0
  25. package/docs/en/guides/basic-features/debug/rsdoctor.mdx +57 -0
  26. package/docs/en/guides/{advanced-features → basic-features/debug}/using-storybook.mdx +2 -0
  27. package/docs/en/guides/basic-features/render/_meta.json +1 -0
  28. package/docs/en/guides/basic-features/render/ssg.mdx +208 -0
  29. package/docs/en/guides/{advanced-features/ssr/cache.mdx → basic-features/render/ssr-cache.mdx} +38 -50
  30. package/docs/en/guides/basic-features/render/ssr.mdx +301 -0
  31. package/docs/en/guides/basic-features/render/streaming-ssr.mdx +230 -0
  32. package/docs/en/guides/basic-features/routes.mdx +275 -263
  33. package/docs/en/guides/basic-features/static-assets/_meta.json +1 -0
  34. package/docs/en/guides/basic-features/static-assets.mdx +1 -1
  35. package/docs/en/guides/basic-features/testing/_meta.json +1 -0
  36. package/docs/en/guides/basic-features/testing/cypress.mdx +95 -0
  37. package/docs/en/guides/basic-features/testing/jest.mdx +148 -0
  38. package/docs/en/guides/basic-features/testing/playwright.mdx +111 -0
  39. package/docs/en/guides/basic-features/testing/vitest.mdx +100 -0
  40. package/docs/en/guides/concept/_meta.json +1 -4
  41. package/docs/en/guides/concept/entries.mdx +78 -47
  42. package/docs/en/guides/get-started/_meta.json +1 -7
  43. package/docs/en/guides/get-started/introduction.mdx +1 -1
  44. package/docs/en/guides/get-started/quick-start.mdx +1 -2
  45. package/docs/en/guides/get-started/tech-stack.mdx +4 -6
  46. package/docs/en/guides/get-started/upgrade.mdx +16 -2
  47. package/docs/en/guides/topic-detail/framework-plugin/_meta.json +1 -1
  48. package/docs/en/guides/topic-detail/generator/_meta.json +1 -1
  49. package/docs/en/guides/topic-detail/generator/create/_meta.json +1 -5
  50. package/docs/en/guides/topic-detail/generator/create/config.mdx +0 -10
  51. package/docs/en/guides/topic-detail/generator/create/use.mdx +0 -1
  52. package/docs/en/guides/topic-detail/generator/new/_meta.json +1 -5
  53. package/docs/en/guides/topic-detail/generator/plugin/_meta.json +1 -1
  54. package/docs/en/guides/troubleshooting/_meta.json +1 -6
  55. package/docs/en/tutorials/first-app/c03-css.mdx +1 -1
  56. package/docs/zh/apis/app/runtime/core/use-loader.mdx +1 -1
  57. package/docs/zh/community/blog/_meta.json +1 -6
  58. package/docs/zh/components/deploy.mdx +1 -1
  59. package/docs/zh/components/init-app.mdx +0 -1
  60. package/docs/zh/components/init-rspack-app.mdx +0 -1
  61. package/docs/zh/components/ssr-monitor.mdx +3 -0
  62. package/docs/zh/configure/_meta.json +1 -1
  63. package/docs/zh/configure/app/output/ssg.mdx +49 -139
  64. package/docs/zh/configure/app/tools/swc.mdx +1 -1
  65. package/docs/zh/configure/app/tools/tailwindcss.mdx +1 -1
  66. package/docs/zh/guides/advanced-features/_meta.json +0 -8
  67. package/docs/zh/guides/advanced-features/bff/_meta.json +1 -6
  68. package/docs/zh/guides/advanced-features/rsbuild-plugin.mdx +2 -2
  69. package/docs/zh/guides/advanced-features/rspack-start.mdx +8 -24
  70. package/docs/zh/guides/basic-features/_meta.json +31 -9
  71. package/docs/zh/guides/basic-features/css/_meta.json +1 -0
  72. package/docs/zh/guides/basic-features/css/css-in-js.mdx +34 -0
  73. package/docs/zh/guides/basic-features/css/css.mdx +25 -0
  74. package/docs/zh/guides/basic-features/{css.mdx → css/tailwindcss.mdx} +3 -64
  75. package/docs/zh/guides/basic-features/data/_meta.json +1 -4
  76. package/docs/zh/guides/basic-features/data/data-fetch.mdx +98 -214
  77. package/docs/zh/guides/basic-features/data/data-write.mdx +54 -55
  78. package/docs/zh/guides/basic-features/debug/_meta.json +1 -0
  79. package/docs/zh/guides/basic-features/debug/rsdoctor.mdx +57 -0
  80. package/docs/zh/guides/{advanced-features → basic-features/debug}/using-storybook.mdx +1 -1
  81. package/docs/zh/guides/basic-features/render/_meta.json +1 -0
  82. package/docs/zh/guides/basic-features/render/ssg.mdx +210 -0
  83. package/docs/zh/guides/{advanced-features/ssr/cache.mdx → basic-features/render/ssr-cache.mdx} +16 -26
  84. package/docs/zh/guides/basic-features/render/ssr.mdx +309 -0
  85. package/docs/zh/guides/{advanced-features/ssr/stream.mdx → basic-features/render/streaming-ssr.mdx} +22 -37
  86. package/docs/zh/guides/basic-features/routes.mdx +252 -237
  87. package/docs/zh/guides/basic-features/static-assets/_meta.json +1 -0
  88. package/docs/zh/guides/basic-features/static-assets.mdx +2 -6
  89. package/docs/zh/guides/basic-features/testing/_meta.json +1 -0
  90. package/docs/zh/guides/basic-features/testing/cypress.mdx +95 -0
  91. package/docs/zh/guides/basic-features/testing/jest.mdx +148 -0
  92. package/docs/zh/guides/basic-features/testing/playwright.mdx +112 -0
  93. package/docs/zh/guides/basic-features/testing/vitest.mdx +100 -0
  94. package/docs/zh/guides/concept/_meta.json +1 -4
  95. package/docs/zh/guides/concept/entries.mdx +80 -58
  96. package/docs/zh/guides/get-started/_meta.json +1 -7
  97. package/docs/zh/guides/get-started/introduction.mdx +2 -2
  98. package/docs/zh/guides/get-started/quick-start.mdx +1 -2
  99. package/docs/zh/guides/get-started/tech-stack.mdx +8 -10
  100. package/docs/zh/guides/get-started/upgrade.mdx +15 -1
  101. package/docs/zh/guides/topic-detail/framework-plugin/_meta.json +1 -1
  102. package/docs/zh/guides/topic-detail/generator/_meta.json +1 -1
  103. package/docs/zh/guides/topic-detail/generator/create/_meta.json +1 -5
  104. package/docs/zh/guides/topic-detail/generator/create/config.mdx +0 -10
  105. package/docs/zh/guides/topic-detail/generator/create/use.mdx +0 -1
  106. package/docs/zh/guides/topic-detail/generator/new/_meta.json +1 -5
  107. package/docs/zh/guides/topic-detail/generator/plugin/_meta.json +1 -1
  108. package/docs/zh/guides/troubleshooting/_meta.json +1 -6
  109. package/docs/zh/tutorials/first-app/c03-css.mdx +1 -1
  110. package/i18n.json +16 -4
  111. package/package.json +6 -6
  112. package/rspress.config.ts +1 -1
  113. package/src/components/ContentCard/index.tsx +1 -1
  114. package/src/components/Sandpack/index.tsx +1 -1
  115. package/src/components/ShowcaseList/index.tsx +1 -1
  116. package/src/i18n/index.ts +1 -1
  117. package/src/pages/index.tsx +2 -2
  118. package/docs/en/apis/app/hooks/config/storybook.mdx +0 -37
  119. package/docs/en/guides/advanced-features/ssg.mdx +0 -116
  120. package/docs/en/guides/advanced-features/ssr/_meta.json +0 -5
  121. package/docs/en/guides/advanced-features/ssr/index.mdx +0 -23
  122. package/docs/en/guides/advanced-features/ssr/stream.mdx +0 -248
  123. package/docs/en/guides/advanced-features/ssr/usage.mdx +0 -341
  124. package/docs/en/guides/advanced-features/ssr.mdx +0 -555
  125. package/docs/zh/apis/app/hooks/config/storybook.mdx +0 -38
  126. package/docs/zh/guides/advanced-features/ssg.mdx +0 -116
  127. package/docs/zh/guides/advanced-features/ssr/_meta.json +0 -5
  128. package/docs/zh/guides/advanced-features/ssr/index.mdx +0 -23
  129. package/docs/zh/guides/advanced-features/ssr/usage.mdx +0 -329
  130. /package/docs/en/guides/basic-features/{mock.mdx → debug/mock.mdx} +0 -0
  131. /package/docs/en/guides/basic-features/{proxy.mdx → debug/proxy.mdx} +0 -0
  132. /package/docs/en/guides/basic-features/{json-files.mdx → static-assets/json-files.mdx} +0 -0
  133. /package/docs/en/guides/basic-features/{svg-assets.mdx → static-assets/svg-assets.mdx} +0 -0
  134. /package/docs/en/guides/basic-features/{wasm-assets.mdx → static-assets/wasm-assets.mdx} +0 -0
  135. /package/docs/zh/guides/basic-features/{css-modules.mdx → css/css-modules.mdx} +0 -0
  136. /package/docs/zh/guides/basic-features/{mock.mdx → debug/mock.mdx} +0 -0
  137. /package/docs/zh/guides/basic-features/{proxy.mdx → debug/proxy.mdx} +0 -0
  138. /package/docs/zh/guides/basic-features/{json-files.mdx → static-assets/json-files.mdx} +0 -0
  139. /package/docs/zh/guides/basic-features/{svg-assets.mdx → static-assets/svg-assets.mdx} +0 -0
  140. /package/docs/zh/guides/basic-features/{wasm-assets.mdx → static-assets/wasm-assets.mdx} +0 -0
@@ -5,15 +5,17 @@ sidebar_position: 4
5
5
 
6
6
  # 数据写入
7
7
 
8
- Data Loader 章节中,介绍了 Modern.js 获取数据的方式,你可能会遇到两个问题:
9
- 1. 如何更新 Data Loader 中的数据?
8
+ [数据获取](/guides/basic-features/data/data-fetch)章节中,介绍了 Modern.js 获取数据的方式,你可能会遇到两个问题:
9
+
10
+ 1. 如何更新 Data Loader 返回的数据?
10
11
  2. 如何将新的数据传递到服务器?
11
12
 
12
- EdenX 对此的解决方案是 DataAction。
13
+ Modern.js 中,可以通过 Data Action 解决和实现。
14
+
15
+ ## 什么是 Data Action
13
16
 
14
- ## 基本示例
17
+ Modern.js 推荐使用[约定式路由](/guides/basic-features/routes)做路由的管理,每个路由组件(`layout.ts`,`page.ts` 或 `$.tsx`)都可以有一个同名的 `.data` 文件。这些文件可以导出一个 `action` 函数,我们称为 Data Action,开发者可以在合适的时机调用它:
15
18
 
16
- Data Action 和 Data Loader 一样,也是基于约定式路由的,通过 Modern.js 的[约定式(嵌套)路由](/guides/basic-features/routes#约定式路由),每个路由组件(`layout.ts`,`page.ts` 或 `$.tsx`)可以有一个同名的 `data` 文件,`data` 文件中可以导出一个命名为 `action` 的函数。
17
19
  ```bash
18
20
  .
19
21
  └── routes
@@ -21,17 +23,21 @@ Data Action 和 Data Loader 一样,也是基于约定式路由的,通过 Mod
21
23
  ├── layout.tsx
22
24
  └── layout.data.ts
23
25
  ```
24
- 在文件中定义以下代码:
26
+
27
+ 在 `routes/user/layout.data.ts` 文件中,可以导出一个 Data Action 函数:
28
+
25
29
  ```ts title="routes/user/layout.data.ts"
26
30
  import type { ActionFunction } from '@modern-js/runtime/router';
27
31
 
28
32
  export const action: ActionFunction = ({ request }) => {
29
- const newUser = await request.json();
30
- const name = newUser.name;
31
- return updateUserProfile(name);
33
+ const newUser = await request.json();
34
+ const name = newUser.name;
35
+ return updateUserProfile(name);
32
36
  }
33
37
  ```
34
38
 
39
+ 在路由组件中,你可以通过 `useFetcher` 获取对应 `submit` 函数,执行并触发 Data Action:
40
+
35
41
  ```tsx title="routes/user/layout.tsx"
36
42
  import {
37
43
  useFetcher,
@@ -64,41 +70,24 @@ export default () => {
64
70
  }
65
71
  ```
66
72
 
67
- 这里当执行 submit 后,会触发定义的 action 函数;在 action 函数中,可以通过 request (request.json,request.formData)获取提交的数据,获取数据后,再发送数据到服务端。
73
+ 当执行 `submit` 后,会触发定义的 `action` 函数。在 `action` 函数中,可以通过[入参](/guides/basic-features/data/data-write.html#入参)获取提交的数据,最终发送数据到服务端。
68
74
 
69
- action 函数执行完,会执行 loader 函数代码,并更新对应的数据和视图。
75
+ `action` 函数执行完后,Modern.js 将自动执行 `loader` 函数代码,并更新对应的数据和视图。
70
76
 
71
77
  ![action flow](https://lf3-static.bytednsdoc.com/obj/eden-cn/ulkl/ljhwZthlaukjlkulzlp/action-flow.png)
72
78
 
73
-
74
-
75
- ## 为什么要提供 Data Action
76
-
77
- Modern.js 中提供 Data Action 主要是为了使 UI 和服务器的状态能保持同步,通过这种方式可以减少状态管理的负担,
78
- 传统的状态管理方式,会在客户端和远程分别持有状态:
79
-
80
- ![traditional state manage](https://lf3-static.bytednsdoc.com/obj/eden-cn/ulkl/ljhwZthlaukjlkulzlp/action-state-manage.png)
81
-
82
- 而在 Modern.js 中,我们希望通过 Loader 和 Action 帮助开发者自动的同步客户端和服务端的状态:
83
-
84
- ![state manage](https://lf3-static.bytednsdoc.com/obj/eden-cn/ulkl/ljhwZthlaukjlkulzlp/action-state-manage1.png)
85
-
86
- 如果项目中组件共享的数据主要来自于服务端的状态,则无需在项目引入客户端状态管理库。可以使用 Data Loader 请求数据,通过 [`useRouteLoaderData`](/guides/basic-features/data/data-fetch.md) 在子组件中共享数据,使用 Data Action 修改和同步服务端的状态。
87
-
88
-
89
-
90
79
  ## `action` 函数
91
80
 
92
- 与 `loader` 函数一样,`action` 函数有两个入参,`params` 和 `request`:
81
+ 与 `loader` 函数一样,`action` 函数有两个入参,`params` 和 `request`。
93
82
 
94
- ### `params`
83
+ ### params
95
84
 
96
- 当路由文件通过 `[]` 时,会作为[动态路由](/guides/basic-features/routes#动态路由),动态路由片段会作为参数传入 `action` 函数:
85
+ `params` 是当路由为[动态路由](/guides/basic-features/routes#动态路由)时动态路由片段,会作为参数传入 `action` 函数:
97
86
 
98
- ```tsx
99
- // routes/user/[id]/page.data.ts
87
+ ```tsx title="routes/user/[id]/page.data.ts"
100
88
  import { ActionFunctionArgs } from '@modern-js/runtime/router';
101
89
 
90
+ // 访问 /user/123 时,函数的参数为 `{ params: { id: '123' } }`
102
91
  export const action = async ({ params }: ActionFunctionArgs) => {
103
92
  const { id } = params;
104
93
  const res = await fetch(`https://api/user/${id}`);
@@ -106,18 +95,11 @@ export const action = async ({ params }: ActionFunctionArgs) => {
106
95
  };
107
96
  ```
108
97
 
109
- 当访问 `/user/123` 时,`action` 函数的参数为 `{ params: { id: '123' } }`。
110
-
98
+ ### request
111
99
 
112
- ### `request`
100
+ `request` 是一个 [Fetch Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) 实例。通过 `request`,可以在 action 函数中获取到浏览器端提交的数据,如 `request.json()`,`request.formData()`,`request.json()` 等。具体使用哪个 API,请参考[数据类型](#数据类型)。
113
101
 
114
- `request` 是一个 [Fetch Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) 实例。
115
-
116
- 通过 `request`,可以在 action 函数中获取到客户端提交的数据,如 `request.json()`,`request.formData()`,`request.json()` 等,
117
- 具体应该使用哪个 API,请参考[数据类型](#数据类型)。
118
-
119
- ```tsx
120
- // routes/user/[id]/page.data.ts
102
+ ```tsx title="routes/user/[id]/page.data.ts"
121
103
  import { ActionFunctionArgs } from '@modern-js/runtime/router';
122
104
 
123
105
  export const action = async ({ request }: ActionFunctionArgs) => {
@@ -131,13 +113,12 @@ export const action = async ({ request }: ActionFunctionArgs) => {
131
113
  `action` 函数的返回值可以是任何可序列化的内容,也可以是一个 [Fetch Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) 实例,
132
114
  可以通过 [`useActionData`](https://reactrouter.com/en/main/hooks/use-action-data) 访问 response 中内容。
133
115
 
134
-
135
116
  ## useSubmit 和 useFetcher
136
117
 
137
118
  ### 区别
138
119
 
139
- 你可以通过 [`useSubmit`](https://reactrouter.com/en/main/hooks/use-submit) 或 [`useFetcher`](https://reactrouter.com/en/main/hooks/use-fetcher) 调用 action,它们的区别是通过
140
- `useSubmit` 调用 action,会触发浏览器的导航,通过 `useFetcher` 则不会触发浏览器的导航。
120
+ 你可以通过 [`useSubmit`](https://reactrouter.com/en/main/hooks/use-submit) 或 [`useFetcher`](https://reactrouter.com/en/main/hooks/use-fetcher) 调用 Data Action。它们的区别是通过
121
+ `useSubmit` 调用,会触发浏览器的导航,通过 `useFetcher` 则不会触发浏览器的导航。
141
122
 
142
123
  useSubmit:
143
124
 
@@ -147,19 +128,19 @@ submit(null, { method: "post", action: "/logout" });
147
128
  ```
148
129
 
149
130
  useFetcher:
131
+
150
132
  ```ts
151
133
  const { submit } = useFetcher();
152
134
  submit(null, { method: "post", action: "/logout" });
153
135
  ```
154
136
 
155
- `submit` 函数有两个入参,`method` `action`,`method` 相当于表单提交时的 `method`,大部分写入数据的场景下,`method` 可以传入 `post`,
156
- `action` 用来指定触发哪个路由组件的 `action`,如果未传入 `action` 入参,默认会触发当前路由组件的 action,即 `user/page.tsx` 组件或子组件中执行 submit,
157
- 会触发 `user/page.data.ts` 中定义的 action。
137
+ `submit` 函数有两个入参,第一个入参是传递到服务端的 `formData`。第二个入参是可选参数,其中
138
+ - `method` 相当于表单提交时的 `method`,大部分写入数据的场景下,`method` 可以传入 `post`。
139
+ - `action` 用来指定触发哪个路由组件的 Data Action,如果未传入 `action` 入参,默认会触发当前路由组件的 action,即 `user/page.tsx` 组件或子组件中执行 submit,会触发 `user/page.data.ts` 中定义的 action。
158
140
 
159
141
  :::info
160
- 这两个 API 更多的信息可参考相关文档:
161
- - [`useSubmit`](https://reactrouter.com/en/main/hooks/use-submit)
162
- - [`useFetcher`](https://reactrouter.com/en/main/hooks/use-fetcher)
142
+
143
+ 更多 API 的信息可参考相关文档:[`useSubmit`](https://reactrouter.com/en/main/hooks/use-submit)、[`useFetcher`](https://reactrouter.com/en/main/hooks/use-fetcher)。
163
144
 
164
145
  :::
165
146
 
@@ -167,7 +148,9 @@ submit(null, { method: "post", action: "/logout" });
167
148
  ### 数据类型
168
149
 
169
150
  `submit` 函数的第一个入参,可以接受不同类型的值。
151
+
170
152
  如 `FormData`:
153
+
171
154
  ```ts
172
155
  let formData = new FormData();
173
156
  formData.append("cheese", "gouda");
@@ -176,6 +159,7 @@ submit(formData);
176
159
  ```
177
160
 
178
161
  或 `URLSearchParams` 类型的值:
162
+
179
163
  ```ts
180
164
  let searchParams = new URLSearchParams();
181
165
  searchParams.append("cheese", "gouda");
@@ -183,7 +167,8 @@ submit(searchParams);
183
167
  // In the action, you can get the data by request.json
184
168
  ```
185
169
 
186
- 或任意 `URLSearchParams` 构造函数可接受的值
170
+ 或任意 `URLSearchParams` 构造函数可接受的值:
171
+
187
172
  ```ts
188
173
  submit("cheese=gouda&toasted=yes");
189
174
  submit([
@@ -207,7 +192,7 @@ submit(
207
192
  // In the action, you can get the data by request.formData
208
193
  ```
209
194
 
210
- 也可以指定为 json 编码:
195
+ 你也可以通过第二个参数,指定为编码方式:
211
196
 
212
197
  ```tsx
213
198
  submit(
@@ -224,12 +209,26 @@ submit('{"key":"value"}', {
224
209
  ```
225
210
 
226
211
  或提交纯文本:
212
+
227
213
  ```ts
228
214
  submit("value", { method: "post", encType: "text/plain" });
229
215
  // In the action, you can get the data by request.text
230
216
  ```
231
217
 
218
+ ## 为什么要提供 Data Action
219
+
220
+ Modern.js 中提供 Data Action 主要是为了使 UI 和服务器的状态能保持同步,通过这种方式可以减少状态管理的负担,
221
+ 传统的状态管理方式,会在浏览器端和远程分别持有状态:
222
+
223
+ ![traditional state manage](https://lf3-static.bytednsdoc.com/obj/eden-cn/ulkl/ljhwZthlaukjlkulzlp/action-state-manage.png)
224
+
225
+ 而在 Modern.js 中,我们希望通过 Loader 和 Action 帮助开发者自动的同步浏览器端和服务端的状态:
226
+
227
+ ![state manage](https://lf3-static.bytednsdoc.com/obj/eden-cn/ulkl/ljhwZthlaukjlkulzlp/action-state-manage1.png)
228
+
229
+ 如果项目中组件共享的数据主要来自于服务端的状态,则无需在项目引入浏览器端状态管理库。可以使用 Data Loader 请求数据,通过 [`useRouteLoaderData`](/guides/basic-features/data/data-fetch.md) 在子组件中共享数据,使用 Data Action 修改和同步服务端的状态。
230
+
232
231
 
233
232
  ## CSR 和 SSR
234
233
 
235
- 与 Data Loader 一样,SSR 项目中,Data Action 是在服务端执行的(框架会自动发请求触发 Data Action),而在 CSR 项目中,Data Action 是在客户端执行的。
234
+ 与 Data Loader 一样,SSR 项目中,Data Action 是在服务端执行的(框架会自动发请求触发 Data Action),而在 CSR 项目中,Data Action 是在浏览器端执行的。
@@ -0,0 +1 @@
1
+ ["mock", "proxy", "rsdoctor", "using-storybook"]
@@ -0,0 +1,57 @@
1
+ import { PackageManagerTabs } from '@theme';
2
+
3
+ # 使用 Rsdoctor
4
+
5
+ Rsdoctor 是一个支持 Webpack 及 Rspack 构建分析工具。在 Modern.js 中,我们推荐使用 Rsdoctor 来对构建过程与构建产物进行诊断和分析。
6
+
7
+ ## 安装依赖
8
+
9
+ 根据项目是 Rspack 或 Webpack 构建,选择对应的插件安装。
10
+
11
+ ### Rspack 插件
12
+
13
+ <PackageManagerTabs command="add @rsdoctor/rspack-plugin -D" />
14
+
15
+ ### Webpack 插件
16
+
17
+ <PackageManagerTabs command="add @rsdoctor/webpack-plugin -D" />
18
+
19
+ ## 注册插件
20
+
21
+ 在 `modern.config.ts` 中,你可以通过 `tools.bundlerChain` 来注册 Rspack 或 Webpack 插件,参考:
22
+
23
+ ```ts title="modern.config.ts"
24
+ import { RsdoctorRspackPlugin } from '@rsdoctor/rspack-plugin';
25
+
26
+ export default {
27
+ // ...
28
+ tools: {
29
+ rspack(config, { appendPlugins }) {
30
+ // 仅在 RSDOCTOR 为 true 时注册插件,因为插件会增加构建耗时
31
+ if (process.env.RSDOCTOR) {
32
+ appendPlugins(
33
+ new RsdoctorRspackPlugin({
34
+ // 插件选项
35
+ }),
36
+ );
37
+ }
38
+ },
39
+ },
40
+ };
41
+ ```
42
+
43
+ :::note
44
+ 上述代码是使用 Rspack 时的示例,如果使用 Webpack 请自行切换插件。
45
+ :::
46
+
47
+ ## 执行构建
48
+
49
+ 在你可以在项目内执行 build 命令,在完成构建后,Rsdoctor 会自动打开本次构建的分析页面。
50
+
51
+ ```bash
52
+ RSDOCTOR=true npm run build
53
+ ```
54
+
55
+ ## 相关文档
56
+
57
+ 更多内容请查阅 [Rsdoctor 官网文档](https://rsdoctor.dev/)。
@@ -229,4 +229,4 @@ Modern.js 的配置文件默认为 `modern.config.(j|t)s`,配置请查看 [mod
229
229
 
230
230
  若原来项目中包含了 Babel 等配置,需要对应的写在 modern 配置中,大部分 Babel 配置已经包含进了 Modern.js。
231
231
 
232
- 安装完成后进行相应的[配置](/guides/advanced-features/using-storybook#配置)。
232
+ 安装完成后进行相应的[配置](/guides/basic-features/debug/using-storybook#配置)。
@@ -0,0 +1 @@
1
+ ["ssr", "streaming-ssr", "ssr-cache", "ssg"]
@@ -0,0 +1,210 @@
1
+ ---
2
+ title: 静态站点生成(SSG)
3
+ ---
4
+
5
+ # 静态站点生成(SSG)
6
+
7
+ SSG(Static Site Generation)是一种基于数据与模板,在构建时渲染完整静态网页的技术解决方案。这意味着在生产环境中,页面默认就是有内容的,并且可以被 CDN 缓存。对于无需数据的页面,SSG 可以提供更好的性能和更高的安全性。
8
+
9
+ ## 启用 SSG
10
+
11
+ 我们首先需要执行 `pnpm run new` 启用 SSG 功能:
12
+
13
+ ```bash
14
+ ? 请选择你想要的操作 启用可选功能
15
+ ? 请选择功能名称 启用「SSG」功能
16
+ ```
17
+
18
+ 执行命令后,在 `modern.config.ts` 中注册 SSG 插件:
19
+
20
+ ```ts title="modern.config.ts"
21
+ import { ssgPlugin } from '@modern-js/plugin-ssg';
22
+
23
+ export default defineConfig({
24
+ output: {
25
+ ssg: true,
26
+ },
27
+ plugins: [..., ssgPlugin()],
28
+ });
29
+ ```
30
+
31
+ ## 开发环境调试
32
+
33
+ SSG 也是在 Node.js 环境渲染页面,因此我们可以在**开发阶段开启 SSR**,提前暴露代码问题,验证 SSG 渲染效果:
34
+
35
+ ```ts title="modern.config.ts"
36
+ export default defineConfig({
37
+ server: {
38
+ ssr: process.env.NODE_ENV === 'development',
39
+ }
40
+ }
41
+ ```
42
+
43
+ ## 在约定式路由中使用
44
+
45
+ **约定式路由**中,Modern.js 根据入口下的文件结构生成路由,因此框架能够收集完整的路由信息。
46
+
47
+ ### 基本用法
48
+
49
+ 例如,以下是一个使用约定式路由的项目目录结构:
50
+
51
+ ```bash
52
+ .
53
+ └── routes
54
+ ├── layout.tsx
55
+ ├── page.tsx
56
+ └── user
57
+ ├── layout.tsx
58
+ ├── page.tsx
59
+ └── profile
60
+ └── page.tsx
61
+ ```
62
+
63
+ 上述文件目录将会生成以下三条路由:
64
+
65
+ - `/`
66
+ - `/user`
67
+ - `/user/profile`
68
+
69
+ :::tip
70
+ 如果还不了解约定式路由的规则,可以先查看[路由方案](/guides/basic-features/routes)。
71
+
72
+ :::
73
+
74
+ 在 `src/routes/page.tsx` 中添加组件代码:
75
+
76
+ ```jsx title="src/routes/page.tsx"
77
+ export default () => {
78
+ return <div>Index Page</div>;
79
+ };
80
+ ```
81
+
82
+ 在项目根路径下执行 `pnpm run dev` 命令,查看 `dist/` 目录,此时只生成一个 HTML 文件 `main/index.html`。
83
+
84
+ 在项目根路径下执行 `pnpm run build` 命令,构建完成后,查看 `dist/` 目录,此时生成 `main/index.html`、`main/user/index.html` 和 `main/user/profile/index.html` 三个 HTML 文件,内容分别对应上述三条路由。
85
+
86
+ **约定式路由**中的每一条路由,都会生成一个单独的 HTML 文件。查看 `main/index.html`,可以发现包含 `Index Page` 的文本内容,这正是 SSG 的效果。
87
+
88
+ 执行 `pnpm run serve` 启动项目后,访问页面,在浏览器我们工具的 Network 窗口,查看请求返回的文档,文档包含组件渲染后的完整页面内容。
89
+
90
+ ### 阻止默认行为
91
+
92
+ 默认情况下,**约定式路由**的路由会全部开启 SSG。Modern.js 提供了另一个字段,用来阻止默认的 SSG 行为。
93
+
94
+ 例如以下目录结构,`/`、`/user`、`/user/profle` 三条路由都开启 SSG:
95
+
96
+ ```bash
97
+ .
98
+ ├── src
99
+ │ └── routes
100
+ │ ├── layout.tsx
101
+ │ ├── page.tsx
102
+ │ └── user
103
+ │ ├── layout.tsx
104
+ │ ├── page.tsx
105
+ │ └── profile
106
+ │ └── page.tsx
107
+ ```
108
+
109
+ 可以通过配置 `preventDefault` 来禁用某些路由的默认行为。进行下面配置后,最终只会生成 `/`、`/user/profle` 两条路由的 SSG 页面:
110
+
111
+ ```js
112
+ export default defineConfig({
113
+ output: {
114
+ ssg: {
115
+ preventDefault: ['/user'],
116
+ },
117
+ },
118
+ });
119
+ ```
120
+
121
+ ## 在自控式路由中使用
122
+
123
+ **自控式路由**是通过组件代码定义路由,需要应用运行起来才能获取准确的路由信息。因此,无法开箱即用的使用 SSG 功能。开发者需要通过配置告知 Modern.js 框架,哪些路由需要开启 SSG 功能。
124
+
125
+ 例如有以下代码,包含多条路由,设置 `output.ssg` 为 `true` 时,默认只会渲染入口路由即 `/`:
126
+
127
+ import SelfRouteExample from '@site-docs/components/self-route-example';
128
+
129
+ <SelfRouteExample />
130
+
131
+ 如果我们希望同时开启 `/about` 的 SSG 功能,可以配置 `output.ssg`:
132
+
133
+ ```ts title="modern.config.ts"
134
+ export default defineConfig({
135
+ output: {
136
+ ssg: {
137
+ routes: ['/', '/about'],
138
+ },
139
+ },
140
+ });
141
+ ```
142
+
143
+ 执行 `pnpm run build` 后,可以看到 `dist/` 目录中,新增了一个 `main/about/index.html` 文件。
144
+
145
+ 执行 `pnpm run serve` 启动项目后,访问页面,在浏览器我们工具的 Network 窗口,查看请求返回的文档,文档包含组件渲染后的完整页面内容。
146
+
147
+ :::info
148
+ 以上仅介绍了单入口的情况,更多相关内容可以查看 [API 文档](/configure/app/output/ssg)。
149
+ :::
150
+
151
+ ## 添加路由参数
152
+
153
+ 在 Modern.js 中,部分路由可能是动态的,例如自控式路由中的 `/user/:id` 或是约定式路由中 `user/[id]/page.tsx` 文件生成的路由。
154
+
155
+ 可以在 `output.ssg` 中配置具体的参数,渲染指定参数的路由,例如:
156
+
157
+ ```js
158
+ export default defineConfig({
159
+ output: {
160
+ ssg: {
161
+ routes: [
162
+ {
163
+ url: '/user/:id',
164
+ params: [{
165
+ id: 'modernjs',
166
+ }],
167
+ },
168
+ ],
169
+ },
170
+ },
171
+ });
172
+ ```
173
+
174
+ 此时,`/user/modernjs` 路由会被渲染,并且在渲染时,会将 `id` 参数传递给组件。当配置多个值时,对应会生成多张页面。
175
+
176
+ :::note
177
+ 动态路由和 SSG 的组合,在根据 CMS 系统数据变更,实时生成静态页面时非常有用。
178
+ :::
179
+
180
+
181
+ ## 配置渲染请求头
182
+
183
+ Modern.js 支持为具体入口或路由配置请求头,例如:
184
+
185
+ ```js
186
+ export default defineConfig({
187
+ output: {
188
+ ssg: {
189
+ headers: {
190
+ "x-tt-env": "ppe_modernjs"
191
+ },
192
+ routes: [
193
+ '/',
194
+ {
195
+ url: '/about',
196
+ headers: {
197
+ "from": "modern-website"
198
+ },
199
+ },
200
+ ],
201
+ },
202
+ },
203
+ });
204
+ ```
205
+
206
+ 上述配置中,为所有路由设置了 `x-tt-env` 请求头,单独为 `/about` 路由设置了 `from` 请求头。
207
+
208
+ :::tip
209
+ 路由中设置的 `headers` 会覆盖入口中设置的 `headers`。
210
+ :::
@@ -1,23 +1,20 @@
1
1
  ---
2
- sidebar_position: 3
3
- title: 缓存
2
+ title: 渲染缓存
4
3
  ---
5
4
 
6
5
  # 渲染缓存
7
6
 
8
- 有时我们会将计算结果进行缓存,例如 React useMemo, useCallback Hook
9
- 通过缓存我们可以减少计算的次数来减少 CPU 资源占用,提高用户体验。
7
+ 在开发应用时,有时我们会将计算结果进行缓存,例如使用 React `useMemo`、`useCallback` Hook。通过缓存我们可以减少计算的次数来减少 CPU 资源占用,提高用户体验。
10
8
 
11
- 通过将服务器端渲染(SSR)结果进行缓存能够减少服务器每次请求时的计算和渲染时间,从而加速页面加载速度,提高用户体验。
12
- 降低服务端负载,节省计算资源,提高用户访问速度。
9
+ Modern.js 支持将服务器端渲染(SSR)结果进行缓存,减少服务器每次请求时的计算和渲染时间,从而加速页面加载速度,提高用户体验。同时,缓存也能降低服务端负载,节省计算资源,提高用户访问速度。
13
10
 
14
- :::info
11
+ :::tip
15
12
  需要 x.43.0+
16
13
  :::
17
14
 
18
15
  ## 配置方式
19
16
 
20
- `server/cache.[t|j]s` 中配置缓存即可开启缓存:
17
+ 在应用中创建 `server/cache.[t|j]s` 文件,并导出 `cacheOption` 配置缓存即可开启 SSR 渲染缓存:
21
18
 
22
19
  ```ts title="server/cache.ts"
23
20
  import type { CacheOption } from '@modern-js/runtime/server';
@@ -41,14 +38,12 @@ export const cacheOption: CacheOption = {
41
38
  ```ts
42
39
  export interface CacheControl {
43
40
  maxAge: number;
44
-
45
41
  staleWhileRevalidate: number;
46
-
47
42
  customKey?: string | ((pathname: string) => string);
48
43
  }
49
44
  ```
50
45
 
51
- 其中 customKey 为自定义缓存 key。默认情况下 Modern.js 将会把请求 pathname 作为 key 进行缓存,但在某些情况下这不能满足你的需求,开发者可以进行自定义。
46
+ 其中 `customKey` 为自定义缓存 key。默认情况下 Modern.js 将会把请求 `pathname` 作为 key 进行缓存,但在某些情况下这不能满足你的需求,开发者可以进行自定义。
52
47
 
53
48
  **Function 类型**
54
49
 
@@ -58,7 +53,7 @@ export type CacheOptionProvider = (
58
53
  ) => Promise<CacheControl | false> | CacheControl | false;
59
54
  ```
60
55
 
61
- 有时开发者需要通过 req 来自定义缓存 key,或者特定 url 时缓存不生效,可以配置为函数的形式进行处理, 例如以下代码:
56
+ 有时开发者需要通过 `req` 来自定义缓存 key,或者特定 URL 时缓存不生效,可以配置为函数的形式进行处理, 例如以下代码:
62
57
 
63
58
  ```ts title="server/cache.ts"
64
59
 
@@ -66,13 +61,11 @@ import type { CacheOption, CacheOptionProvider } from '@modern-js/runtime/server
66
61
 
67
62
  const provider: CacheOptionProvider = (req) => {
68
63
  const { url, headers, ... } = req;
69
-
70
- const key = computedKey(url, headers, ...);
71
-
72
64
  if(url.includes('no-cache=1')) {
73
65
  return false;
74
66
  }
75
67
 
68
+ const key = computedKey(url, headers, ...);
76
69
  return {
77
70
  maxAge: 500, // ms
78
71
  staleWhileRevalidate: 1000, // ms
@@ -89,7 +82,7 @@ export const cacheOption: CacheOption = provider;
89
82
  export type CacheOptions = Record<string, CacheControl | CacheOptionProvider>;
90
83
  ```
91
84
 
92
- 有时开发者面对不同的路由需要应用不同的缓存策略。我们也提供一种映射的方式进行配置, 以下列代码为例子
85
+ 有时开发者面对不同的路由需要应用不同的缓存策略。我们也提供一种映射的方式进行配置, 以下列代码为例:
93
86
 
94
87
  ```ts title="server/cache.ts"
95
88
  import type { CacheOption } from '@modern-js/runtime/server';
@@ -120,14 +113,13 @@ export const cacheOption: CacheOption = {
120
113
  - 路由 `http://xxx/about` 将会应用第二条规则。
121
114
  - 路由 `http://xxx/abc` 将会应用最后一条规则。
122
115
 
123
- 上述 `/home` 和 `/about` 将会作为模式进行匹配,这意味着 `/home/abc` 也会匹配上该规则。
124
- 同时,你也可以在其中编写正则语法:`/home/.+`
116
+ 上述 `/home` 和 `/about` 将会作为模式进行匹配,这意味着 `/home/abc` 也会匹配上该规则。同时,你也可以在其中编写正则语法:`/home/.+`
125
117
 
126
118
  ### 缓存容器
127
119
 
128
- 默认情况下,Server 将会使用内存进行缓存。但通常情况下服务将会部署在 serverless 上。每一次的服务访问可能都是一个新的进程,这样每次访问都不能应用缓存
120
+ 默认情况下,Server 将会使用内存进行缓存。但通常情况下服务将会部署在 Serverless 容器上。每一次的服务访问可能都是一个新的进程,这样每次访问都不能应用缓存。
129
121
 
130
- 故开发者也可以自定义缓存容器,容器需实现接口 `Container`
122
+ 因此,Modern.js 支持开发者自定义缓存容器,容器需实现接口 `Container`:
131
123
 
132
124
  ```ts
133
125
  export interface Container<K = string, V = string> {
@@ -156,7 +148,7 @@ export interface Container<K = string, V = string> {
156
148
  }
157
149
  ```
158
150
 
159
- 以下面代码为例,开发者可实现一个 redis 容器。
151
+ 以下面代码为例,开发者可实现一个 redis 缓存容器。
160
152
 
161
153
  ```ts
162
154
  import type { Container, CacheOption } from '@modern-js/runtime/server';
@@ -194,9 +186,7 @@ export const cacheOption: CacheOption = {
194
186
 
195
187
  ## 缓存标识
196
188
 
197
- 当开启渲染缓存后,Modern.js 将通过响应头 `x-render-cache` 来标识当前请求的缓存状态。
198
-
199
- 下列是一个响应示例
189
+ 当开启渲染缓存后,Modern.js 将通过响应头 `x-render-cache` 来标识当前请求的缓存状态。下面是一个响应示例:
200
190
 
201
191
  ```bash
202
192
  < HTTP/1.1 200 OK
@@ -209,11 +199,11 @@ export const cacheOption: CacheOption = {
209
199
  < Content-Length: 2937
210
200
  ```
211
201
 
212
- `x-render-cache` 可能会有以下几种值
202
+ `x-render-cache` 可能会有以下几种值:
213
203
 
214
204
  | 名称 | 说明 |
215
205
  | ------- | -------------------------------------------------- |
216
206
  | hit | 缓存命中,返回缓存内容 |
217
207
  | stale | 缓存命中,但数据陈旧,返回缓存内容的同时做重新渲染 |
218
208
  | expired | 缓存命中,重新渲染后返回渲染结果 |
219
- | miss | 缓存未命中 |
209
+ | miss | 缓存未命中 |