@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
@@ -1,19 +1,20 @@
1
1
  ---
2
- title: Data writing
3
2
  sidebar_position: 4
4
3
  ---
5
4
 
6
- # Data writing
5
+ # Data Writing
7
6
 
8
- In the Data Loader chapter, the way Modern.js fetch data is introduced. You may encounter two problems.:
9
- 1. How to update the data in Data Loader?
10
- 2. How to write new data to the server?
7
+ In the [Data Fetching](/guides/basic-features/data/data-fetch) section, we introduced how Modern.js fetches data. This might bring up two questions:
11
8
 
12
- EdenX's solution for this is DataAction.
9
+ 1. How do I update the data returned by the Data Loader?
10
+ 2. How do I send new data to the server?
13
11
 
14
- ## Basic Example
12
+ In Modern.js, you can use Data Action to address these scenarios.
13
+
14
+ ## What is Data Action
15
+
16
+ Modern.js recommends managing routes using [conventional routing](/guides/basic-features/routes). Each route component (`layout.ts`, `page.ts`, or `$.tsx`) can have a same-named `.data` file. These files can export an `action` function, known as Data Action, which developers can call at an appropriate time:
15
17
 
16
- Data Action, like Data Loader, is also based on convention routing. Through Modern.js's [nested routing](/guides/basic-features/routes#routing-file-convention), each routing component (`layout.ts`, `page.ts` or `$.tsx`) can have a `data` file with the same name, and a function named `action` can be exported in the `data` file.
17
18
  ```bash
18
19
  .
19
20
  └── routes
@@ -21,17 +22,21 @@ Data Action, like Data Loader, is also based on convention routing. Through Mode
21
22
  ├── layout.tsx
22
23
  └── layout.data.ts
23
24
  ```
24
- Define the following code in the file:
25
+
26
+ You can export a Data Action function in the `routes/user/layout.data.ts` file:
27
+
25
28
  ```ts title="routes/user/layout.data.ts"
26
- import type { ActionFunction } from '@modern-js/runtime/router';
29
+ import type { ActionFunction } from '@modern-js/runtime/router;
27
30
 
28
31
  export const action: ActionFunction = ({ request }) => {
29
- const newUser = await request.json();
30
- const name = newUser.name;
31
- return updateUserProfile(name);
32
+ const newUser = await request.json();
33
+ const name = newUser.name;
34
+ return updateUserProfile(name);
32
35
  }
33
36
  ```
34
37
 
38
+ In the route component, you can use `useFetcher` to get the corresponding `submit` function, which executes and triggers Data Action:
39
+
35
40
  ```tsx title="routes/user/layout.tsx"
36
41
  import {
37
42
  useFetcher,
@@ -64,44 +69,24 @@ export default () => {
64
69
  }
65
70
  ```
66
71
 
67
- Here, when the submit is executed, the defined action function will be triggered; in the action function, the submitted data can be obtained through request (request.json, request.formData, etc.), and the data can be obtained, and then the data can be sent to the server.
72
+ After executing `submit`, the defined `action` function will be triggered. You can get the submitted data from the [parameters](/guides/basic-features/data/data-write.html#parameters) in the `action` function and ultimately send the data to the server.
68
73
 
69
- After the action function is executed, the loader function code will be executed and the corresponding data and views will be updated.
74
+ Once the `action` function executes, Modern.js will automatically run the `loader` function code to update the data and view accordingly.
70
75
 
71
76
  ![action flow](https://lf3-static.bytednsdoc.com/obj/eden-cn/ulkl/ljhwZthlaukjlkulzlp/action-flow.png)
72
77
 
78
+ ## `action` Function
73
79
 
80
+ Similar to the `loader` function, the `action` function takes two parameters: `params` and `request`.
74
81
 
75
- ## Why provide Data Action?
82
+ ### params
76
83
 
77
- Data Action is mainly provided in Modern.js to keep the state of the UI and the server in sync, which can reduce the burden of state management.
78
-
79
- The traditional state management method will hold the state on the client side and remotely respectively::
80
-
81
- ![traditional state manage](https://lf3-static.bytednsdoc.com/obj/eden-cn/ulkl/ljhwZthlaukjlkulzlp/action-state-manage.png)
82
-
83
- In Modern.js, we hope to help developers automatically synchronize the state of the client and server through Loader and Action::
84
-
85
- ![state manage](https://lf3-static.bytednsdoc.com/obj/eden-cn/ulkl/ljhwZthlaukjlkulzlp/action-state-manage1.png)
84
+ `params` is the dynamic route segments when the route is a [dynamic route](/guides/basic-features/routes#dynamic-routes), which are passed as parameters to the `action` function:
86
85
 
87
- If the data shared by the components in the project are the state of the main server, there is no need to introduce a client state management library in the project, request data through Data Loader, through [`useRouteLoaderData`](/guides/basic-fe Atures/data/data-fetch.md) shares data in subcomponents,
88
-
89
- Modify and synchronize the state of the server through Data Action.
90
-
91
-
92
-
93
- ## `action` function
94
-
95
- Like the `loader` function, the `action` function has two parameters, `params` and `request`:
96
-
97
- ### `params`
98
-
99
- When the routing file passes through `[]`, it will be used as [dynamic routing](/guides/basic-features/routes#dynamic routing), and the dynamic routing fragment will be passed into the `action` function as a parameter::
100
-
101
- ```tsx
102
- // routes/user/[id]/page.data.ts
103
- import { ActionFunctionArgs } from '@modern-js/runtime/router';
86
+ ```tsx title="routes/user/[id]/page.data.ts"
87
+ import { ActionFunctionArgs } from '@modern-js/runtime/router;
104
88
 
89
+ // When visiting /user/123, the function parameter is `{ params: { id: '123' } }`
105
90
  export const action = async ({ params }: ActionFunctionArgs) => {
106
91
  const { id } = params;
107
92
  const res = await fetch(`https://api/user/${id}`);
@@ -109,17 +94,13 @@ export const action = async ({ params }: ActionFunctionArgs) => {
109
94
  };
110
95
  ```
111
96
 
112
- When accessing `/user/123`, the parameter of the `action` function is `{ params: { id: '123' } }`.
113
-
97
+ ### request
114
98
 
115
- ### `request`
99
+ `request` is an instance of [Fetch Request](https://developer.mozilla.org/en-US/docs/Web/API/Request).
116
100
 
117
- Through `request`, you can fetch data submitted by the client in the action function, such as `request.json()`, `request.formData()`, `request.json()`, etc.
101
+ Using `request`, you can retrieve data submitted from the client in the action function, such as `request.json()`, `request.formData()`, `request.json()`, etc. Refer to [Data Types](#data-types) for which API to use.
118
102
 
119
- For the specific API, please refer to [data type] (#data-type).
120
-
121
- ```tsx
122
- // routes/user/[id]/page.data.ts
103
+ ```tsx title="routes/user/[id]/page.data.ts"
123
104
  import { ActionFunctionArgs } from '@modern-js/runtime/router';
124
105
 
125
106
  export const action = async ({ request }: ActionFunctionArgs) => {
@@ -130,18 +111,13 @@ export const action = async ({ request }: ActionFunctionArgs) => {
130
111
 
131
112
  ### Return Value
132
113
 
133
- The return value of the `action` function can be any serializable value or a [Fetch Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) instance,
134
-
135
- The data in the response can be accessed through [`useActionData`](https://reactrouter.com/en/main/hooks/use-action-data).
114
+ The return value of the `action` function can be any serializable content or a [Fetch Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) instance. You can access the content via [`useActionData`](https://reactrouter.com/en/main/hooks/use-action-data).
136
115
 
116
+ ## useSubmit and useFetcher
137
117
 
138
- ## useSubmit 和 useFetcher
118
+ ### Difference
139
119
 
140
- ### Differences
141
-
142
- You can use [`useSubmit`](https://reactrouter.com/en/main/hooks/use-submit) or [`useFetcher`](https://reactrouter.com/en/main/hooks/use-fetcher) calls action, and the difference between them is through
143
-
144
- `useSubmit` calls action, which will trigger the browser's navigation, and `useFetcher` will not trigger the browser's navigation.
120
+ You can call Data Action using [`useSubmit`](https://reactrouter.com/en/main/hooks/use-submit) or [`useFetcher`](https://reactrouter.com/en/main/hooks/use-fetcher). The difference is that `useSubmit` triggers browser navigation, while `useFetcher` does not.
145
121
 
146
122
  useSubmit:
147
123
 
@@ -151,29 +127,28 @@ submit(null, { method: "post", action: "/logout" });
151
127
  ```
152
128
 
153
129
  useFetcher:
130
+
154
131
  ```ts
155
132
  const { submit } = useFetcher();
156
133
  submit(null, { method: "post", action: "/logout" });
157
134
  ```
158
135
 
159
- The `submit` function has two input parameters, `method` and `action`. `method` is equivalent to `method` at the time of form submission. In most scenarios where data is written,the `method` can be passed into `post`.
160
-
161
- `action` is used to specify which routing component `action` is triggered. If the `action` parameter is not passed in, the action of the current routing component will be triggered by default, that is,
162
- the execution of submit in the `user/page.tsx` component or subcomponent will trigger the action defined in `user/page.data.ts`.
163
-
136
+ The `submit` function takes two parameters. The first parameter is the `formData` passed to the server. The second parameter is an optional object where:
137
+ - `method` corresponds to the form submission method. In most data writing scenarios, you can set the `method` to `post`.
138
+ - `action` specifies the route component to trigger the Data Action. If not provided, it defaults to the current route component's action. For example, executing submit in `user/page.tsx` or its sub-components will trigger the action defined in `user/page.data.ts`.
164
139
 
165
140
  :::info
166
- For more information about these two APIs, please refer to the relevant documents:
167
- - [`useSubmit`](https://reactrouter.com/en/main/hooks/use-submit)
168
- - [`useFetcher`](https://reactrouter.com/en/main/hooks/use-fetcher)
169
141
 
170
- :::
142
+ More information about the API can be found in the relevant documentation: [`useSubmit`](https://reactrouter.com/en/main/hooks/use-submit), [`useFetcher`](https://reactrouter.com/en/main/hooks/use-fetcher).
171
143
 
144
+ :::
172
145
 
173
- ### Type of data
146
+ ### Data Types
174
147
 
175
148
  The first parameter of the `submit` function can accept different types of values.
176
- Such as `FormData`:
149
+
150
+ For example, `FormData`:
151
+
177
152
  ```ts
178
153
  let formData = new FormData();
179
154
  formData.append("cheese", "gouda");
@@ -181,7 +156,8 @@ submit(formData);
181
156
  // In the action, you can get the data by request.json
182
157
  ```
183
158
 
184
- Or the value of type `URLSearchParams`:
159
+ or `URLSearchParams`:
160
+
185
161
  ```ts
186
162
  let searchParams = new URLSearchParams();
187
163
  searchParams.append("cheese", "gouda");
@@ -189,7 +165,8 @@ submit(searchParams);
189
165
  // In the action, you can get the data by request.json
190
166
  ```
191
167
 
192
- Or any acceptable value of the `URLSearchParams` constructor
168
+ or any value that the `URLSearchParams` constructor accepts:
169
+
193
170
  ```ts
194
171
  submit("cheese=gouda&toasted=yes");
195
172
  submit([
@@ -199,7 +176,7 @@ submit([
199
176
  // In the action, you can get the data by request.json
200
177
  ```
201
178
 
202
- By default, if the first parameter in the `submit` function is an object, the corresponding data will be encoded as `formData`:
179
+ By default, if the first parameter of the `submit` function is an object, the corresponding data will be encoded as `formData`:
203
180
 
204
181
  ```ts
205
182
  submit(
@@ -213,7 +190,7 @@ submit(
213
190
  // In the action, you can get the data by request.formData
214
191
  ```
215
192
 
216
- it can also be specified as json encoding:
193
+ You can also specify the encoding type via the second parameter:
217
194
 
218
195
  ```tsx
219
196
  submit(
@@ -229,13 +206,25 @@ submit('{"key":"value"}', {
229
206
  // In the action, you can get the data by request.json
230
207
  ```
231
208
 
232
- or submit plain text
209
+ or submit plain text:
210
+
233
211
  ```ts
234
212
  submit("value", { method: "post", encType: "text/plain" });
235
213
  // In the action, you can get the data by request.text
236
214
  ```
237
215
 
216
+ ## Why Data Action?
217
+
218
+ Modern.js provides Data Action primarily to keep the UI and server state in sync, reducing the burden of state management. Traditional state management methods maintain state separately on the client and remote server:
219
+
220
+ ![traditional state manage](https://lf3-static.bytednsdoc.com/obj/eden-cn/ulkl/ljhwZthlaukjlkulzlp/action-state-manage.png)
221
+
222
+ In Modern.js, we aim to help developers automatically synchronize client and server state using Loader and Action:
223
+
224
+ ![state manage](https://lf3-static.bytednsdoc.com/obj/eden-cn/ulkl/ljhwZthlaukjlkulzlp/action-state-manage1.png)
225
+
226
+ If the shared data in your project mainly comes from the server, you don't need to introduce a client-side state management library. Use Data Loader to request data and share it in sub-components via [`useRouteLoaderData`](/guides/basic-features/data/data-fetch). Use Data Action to modify and synchronize the server's state.
238
227
 
239
- ## CSR SSR
228
+ ## CSR and SSR
240
229
 
241
- Like Data Loader, in the SSR project, Data Action is executed on the server (the framework will automatically send a request to trigger Data Action), while in the CSR project, Data Action is executed on the client.
230
+ Similar to Data Loader, in SSR projects, Data Action is executed on the server (the framework automatically sends requests to trigger Data Action), while in CSR projects, Data Action is executed on the client.
@@ -0,0 +1 @@
1
+ ["mock", "proxy", "rsdoctor", "using-storybook"]
@@ -0,0 +1,57 @@
1
+ import { PackageManagerTabs } from '@theme';
2
+
3
+ # Using Rsdoctor
4
+
5
+ Rsdoctor is a build analysis tool that supports both Webpack and Rspack. In Modern.js, we recommend using Rsdoctor to diagnose and analyze the build process and build outputs.
6
+
7
+ ## Install Dependencies
8
+
9
+ Depending on whether your project uses Rspack or Webpack, choose the corresponding plugin installation.
10
+
11
+ ### Rspack Plugin
12
+
13
+ <PackageManagerTabs command="add @rsdoctor/rspack-plugin -D" />
14
+
15
+ ### Webpack Plugin
16
+
17
+ <PackageManagerTabs command="add @rsdoctor/webpack-plugin -D" />
18
+
19
+ ## Register Plugin
20
+
21
+ In `modern.config.ts`, you can register the Rspack or Webpack plugin via `tools.bundlerChain`. Refer to the example below:
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
+ // Only register the plugin when RSDOCTOR is true, as the plugin will increase build time.
31
+ if (process.env.RSDOCTOR) {
32
+ appendPlugins(
33
+ new RsdoctorRspackPlugin({
34
+ // Plugin options
35
+ }),
36
+ );
37
+ }
38
+ },
39
+ },
40
+ };
41
+ ```
42
+
43
+ :::note
44
+ The above code is an example of using Rspack. If you are using Webpack, please switch the plugin accordingly.
45
+ :::
46
+
47
+ ## Execute Build
48
+
49
+ You can execute the build command within your project. After the build is complete, Rsdoctor will automatically open the analysis page for the build.
50
+
51
+ ```bash
52
+ RSDOCTOR=true npm run build
53
+ ```
54
+
55
+ ## Related Documentation
56
+
57
+ For more information, please refer to the [Rsdoctor Website](https://rsdoctor.dev/).
@@ -228,3 +228,5 @@ export default config;
228
228
  The default config file path is `modern.config.(j|t)s`, for the detail config, see [modern.js config](/configure/app/usage).
229
229
 
230
230
  If the original project includes configurations for Babel, they need to be written in the modern configuration. Most Babel configurations have already been included in Modern.js.
231
+
232
+ After installation, make the corresponding [configuration](/guides/basic-features/debug/using-storybook#configurations).
@@ -0,0 +1 @@
1
+ ["ssr", "streaming-ssr", "ssr-cache", "ssg"]
@@ -0,0 +1,208 @@
1
+ ---
2
+ ---
3
+
4
+ # Static Site Generation
5
+
6
+ SSG (Static Site Generation) is a technical solution that generates complete static web pages at build time based on data and templates. This means that in a production environment, pages are pre-rendered with content and can be cached by a CDN. SSG can offer better performance and higher security for pages that do not require dynamic data.
7
+
8
+ ## Enabling SSG
9
+
10
+ First, we need to enable the SSG feature by running `pnpm run new`:
11
+
12
+ ```bash
13
+ ? Please select the operation you want: Enable features
14
+ ? Please select the feature name: Enable SSG
15
+ ```
16
+
17
+ After running the command, register the SSG plugin in `modern.config.ts`:
18
+
19
+ ```ts title="modern.config.ts"
20
+ import { ssgPlugin } from '@modern-js/plugin-ssg';
21
+
22
+ export default defineConfig({
23
+ output: {
24
+ ssg: true,
25
+ },
26
+ plugins: [..., ssgPlugin()],
27
+ });
28
+ ```
29
+
30
+ ## Development Debugging
31
+
32
+ Since SSG also renders pages in a Node.js environment, we can enable SSR during the **development phase** to expose code issues early and validate the SSG rendering effect:
33
+
34
+ ```ts title="modern.config.ts"
35
+ export default defineConfig({
36
+ server: {
37
+ ssr: process.env.NODE_ENV === 'development',
38
+ }
39
+ }
40
+ ```
41
+
42
+ ## Using SSG in Conventional Routing
43
+
44
+ In **conventional routing**, Modern.js generates routes based on the file structure under the entry point, allowing the framework to collect complete route information.
45
+
46
+ ### Basic Usage
47
+
48
+ For example, the following is a project directory structure using conventional routing:
49
+
50
+ ```bash
51
+ .
52
+ └── routes
53
+ ├── layout.tsx
54
+ ├── page.tsx
55
+ └── user
56
+ ├── layout.tsx
57
+ ├── page.tsx
58
+ └── profile
59
+ └── page.tsx
60
+ ```
61
+
62
+ The above file directory will generate the following three routes:
63
+
64
+ - `/`
65
+ - `/user`
66
+ - `/user/profile`
67
+
68
+ :::tip
69
+ If you are not familiar with the rules of conventional routing, refer to the [Routing Solution](/guides/basic-features/routes) first.
70
+
71
+ :::
72
+
73
+ Add component code in `src/routes/page.tsx`:
74
+
75
+ ```jsx title="src/routes/page.tsx"
76
+ export default () => {
77
+ return <div>Index Page</div>;
78
+ };
79
+ ```
80
+
81
+ Run the command `pnpm run dev` at the project root and check the `dist/` directory, where only one HTML file `main/index.html` is generated.
82
+
83
+ Run the command `pnpm run build` at the project root, and after the build completes, check the `dist/` directory again. This time, you'll find `main/index.html`, `main/user/index.html`, and `main/user/profile/index.html` files, each corresponding to the routes listed above.
84
+
85
+ Each route in **conventional routing** will generate a separate HTML file. Checking `main/index.html`, you will find it contains the text `Index Page`, which demonstrates the effect of SSG.
86
+
87
+ After running `pnpm run serve` to start the project, inspect the returned document in the Network tab of the browser's development tools. The document includes the fully rendered content from the component.
88
+
89
+ ### Preventing Default Behavior
90
+
91
+ By default, all routes in **conventional routing** have SSG enabled. Modern.js provides another field to prevent the default SSG behavior.
92
+
93
+ For example, in the following directory structure, routes `/`, `/user`, and `/user/profile` all have SSG enabled:
94
+
95
+ ```bash
96
+ .
97
+ ├── src
98
+ │ └── routes
99
+ │ ├── layout.tsx
100
+ │ ├── page.tsx
101
+ │ └── user
102
+ │ ├── layout.tsx
103
+ │ ├── page.tsx
104
+ │ └── profile
105
+ │ └── page.tsx
106
+ ```
107
+
108
+ You can disable the default behavior of certain routes by configuring `preventDefault`. After configuring as shown below, only the SSG pages for `/` and `/user/profile` will be generated:
109
+
110
+ ```js
111
+ export default defineConfig({
112
+ output: {
113
+ ssg: {
114
+ preventDefault: ['/user'],
115
+ },
116
+ },
117
+ });
118
+ ```
119
+
120
+ ## Using SSG in Manual Routing
121
+
122
+ **Manual routing** defines routes through component code, requiring the application to run to obtain accurate route information. Therefore, you cannot use the SSG feature out of the box. Developers need to configure which routes require SSG.
123
+
124
+ For example, consider the following code with multiple routes. By setting `output.ssg` to `true`, it will only render the entry route (`/`) by default.
125
+
126
+ import SelfRouteExample from '@site-docs/components/self-route-example';
127
+
128
+ <SelfRouteExample />
129
+
130
+ If you want to enable SSG for `/about` as well, you can configure `output.ssg`:
131
+
132
+ ```ts title="modern.config.ts"
133
+ export default defineConfig({
134
+ output: {
135
+ ssg: {
136
+ routes: ['/', '/about'],
137
+ },
138
+ },
139
+ });
140
+ ```
141
+
142
+ After running `pnpm run build`, you will see a new `main/about/index.html` file in the `dist/` directory.
143
+
144
+ After running `pnpm run serve` to start the project, inspect the returned document in the Network tab of the browser's development tools. The document includes the fully rendered content from the component.
145
+
146
+ :::info
147
+ The above example introduces single-entry scenarios. For more information, refer to the [API Documentation](/configure/app/output/ssg).
148
+ :::
149
+
150
+ ## Adding Route Parameters
151
+
152
+ In Modern.js, some routes can be dynamic, such as `/user/:id` in manual routing or `/user/[id]/page.tsx` in conventional routing.
153
+
154
+ can configure specific parameters in `output.ssg` to render routes with specified parameters. For example:
155
+
156
+ ```js
157
+ export default defineConfig({
158
+ output: {
159
+ ssg: {
160
+ routes: [
161
+ {
162
+ url: '/user/:id',
163
+ params: [{
164
+ id: 'modernjs',
165
+ }],
166
+ },
167
+ ],
168
+ },
169
+ },
170
+ });
171
+ ```
172
+
173
+ Here, the `/user/modernjs` route will be rendered, and the `id` parameter will be passed to the component during rendering. When multiple values are configured, multiple pages will be generated.
174
+
175
+ :::note
176
+ The combination of dynamic routing and SSG is very useful for generating static pages in real-time based on data changes from a CMS system.
177
+ :::
178
+
179
+ ## Configuring Request Headers for Rendering
180
+
181
+ Modern.js supports configuring request headers for specific entries or routes. For example:
182
+
183
+ ```js
184
+ export default defineConfig({
185
+ output: {
186
+ ssg: {
187
+ headers: {
188
+ "x-tt-env": "ppe_modernjs"
189
+ },
190
+ routes: [
191
+ '/',
192
+ {
193
+ url: '/about',
194
+ headers: {
195
+ "from": "modern-website"
196
+ },
197
+ },
198
+ ],
199
+ },
200
+ },
201
+ });
202
+ ```
203
+
204
+ In the above configuration, the `x-tt-env` request header is set for all routes, and the `from` request header is specifically set for the `/about` route.
205
+
206
+ :::tip
207
+ Headers set in routes will override headers set for entries.
208
+ :::