@modern-js/main-doc 2.58.3 → 2.60.0
Sign up to get free protection for your applications and to get access to all the features.
- package/docs/en/_meta.json +10 -5
- package/docs/en/apis/app/hooks/api/lambda.mdx +4 -48
- package/docs/en/apis/app/hooks/api/middleware.mdx +11 -0
- package/docs/en/apis/app/runtime/core/use-loader.mdx +1 -1
- package/docs/en/community/blog/v2-release-note.mdx +1 -1
- package/docs/en/components/enable-bff.mdx +19 -2
- package/docs/en/components/extend-bff-function.mdx +5 -0
- package/docs/en/components/init-app.mdx +0 -1
- package/docs/en/components/init-rspack-app.mdx +0 -1
- package/docs/en/components/other-plugins.mdx +0 -0
- package/docs/en/components/ssr-monitor.mdx +3 -0
- package/docs/en/configure/app/auto-load-plugin.mdx +4 -0
- package/docs/en/configure/app/output/ssg.mdx +52 -141
- package/docs/en/configure/app/plugins.mdx +2 -2
- package/docs/en/configure/app/tools/esbuild.mdx +1 -1
- package/docs/en/configure/app/tools/swc.mdx +1 -1
- package/docs/en/configure/app/tools/tailwindcss.mdx +1 -1
- package/docs/en/guides/_meta.json +0 -5
- package/docs/en/guides/advanced-features/_meta.json +3 -8
- package/docs/en/guides/advanced-features/bff/_meta.json +1 -1
- package/docs/en/guides/advanced-features/bff/extend-server.mdx +154 -0
- package/docs/en/guides/advanced-features/bff/frameworks.mdx +52 -123
- package/docs/en/guides/advanced-features/bff/function.mdx +108 -80
- package/docs/en/guides/advanced-features/bff/sdk.mdx +40 -51
- package/docs/en/guides/advanced-features/build-performance.mdx +6 -21
- package/docs/en/guides/advanced-features/page-performance/_meta.json +1 -0
- package/docs/en/guides/advanced-features/rspack-start.mdx +6 -14
- package/docs/en/guides/basic-features/_meta.json +31 -9
- package/docs/en/guides/basic-features/css/_meta.json +1 -0
- package/docs/en/guides/basic-features/css/css-in-js.mdx +34 -0
- package/docs/en/guides/basic-features/{css-modules.mdx → css/css-modules.mdx} +0 -4
- package/docs/en/guides/basic-features/css/css.mdx +25 -0
- package/docs/en/guides/basic-features/{css.mdx → css/tailwindcss.mdx} +5 -66
- package/docs/en/guides/basic-features/data/data-fetch.mdx +134 -235
- package/docs/en/guides/basic-features/data/data-write.mdx +66 -77
- package/docs/en/guides/basic-features/debug/_meta.json +1 -0
- package/docs/en/guides/basic-features/debug/rsdoctor.mdx +57 -0
- package/docs/en/guides/{advanced-features → basic-features/debug}/using-storybook.mdx +2 -0
- package/docs/en/guides/basic-features/render/_meta.json +1 -0
- package/docs/en/guides/basic-features/render/ssg.mdx +208 -0
- package/docs/en/guides/{advanced-features/ssr/cache.mdx → basic-features/render/ssr-cache.mdx} +38 -50
- package/docs/en/guides/basic-features/render/ssr.mdx +301 -0
- package/docs/en/guides/basic-features/render/streaming-ssr.mdx +230 -0
- package/docs/en/guides/basic-features/routes.mdx +274 -263
- package/docs/en/guides/basic-features/static-assets/_meta.json +1 -0
- package/docs/en/guides/basic-features/static-assets.mdx +2 -2
- package/docs/en/guides/basic-features/testing/_meta.json +1 -0
- package/docs/en/guides/basic-features/testing/cypress.mdx +95 -0
- package/docs/en/guides/basic-features/testing/jest.mdx +148 -0
- package/docs/en/guides/basic-features/testing/playwright.mdx +111 -0
- package/docs/en/guides/basic-features/testing/vitest.mdx +100 -0
- package/docs/en/guides/concept/entries.mdx +9 -2
- package/docs/en/guides/deprecated.md +2 -0
- package/docs/en/guides/get-started/quick-start.mdx +1 -1
- package/docs/en/guides/get-started/tech-stack.mdx +4 -4
- package/docs/en/guides/topic-detail/_meta.json +0 -6
- package/docs/en/guides/topic-detail/generator/create/config.mdx +0 -10
- package/docs/en/guides/topic-detail/generator/create/use.mdx +0 -1
- package/docs/en/plugin/_meta.json +19 -0
- package/docs/en/plugin/cli-plugins/_meta.json +1 -0
- package/docs/en/plugin/cli-plugins/plugin-bff.mdx +5 -0
- package/docs/en/plugin/cli-plugins/plugin-ssg.mdx +5 -0
- package/docs/en/{guides/rsbuild-plugins → plugin/cli-plugins}/plugin-swc.mdx +7 -0
- package/docs/en/plugin/cli-plugins/plugin-tailwind.mdx +5 -0
- package/docs/en/plugin/cli-plugins.mdx +6 -0
- package/docs/en/{guides/advanced-features/rsbuild-plugin.mdx → plugin/introduction.mdx} +36 -11
- package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/extend.mdx +1 -1
- package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/implement.mdx +3 -3
- package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/plugin-api.mdx +2 -2
- package/docs/en/plugin/rsbuild-plugins/_meta.json +1 -0
- package/docs/en/plugin/rsbuild-plugins.mdx +3 -0
- package/docs/en/tutorials/first-app/c03-css.mdx +1 -1
- package/docs/zh/_meta.json +10 -5
- package/docs/zh/apis/app/hooks/api/lambda.mdx +5 -48
- package/docs/zh/apis/app/hooks/api/middleware.mdx +11 -0
- package/docs/zh/apis/app/runtime/core/use-loader.mdx +1 -1
- package/docs/zh/community/blog/v2-release-note.mdx +1 -1
- package/docs/zh/components/enable-bff.mdx +19 -2
- package/docs/zh/components/extend-bff-function.mdx +5 -0
- package/docs/zh/components/init-app.mdx +0 -1
- package/docs/zh/components/init-rspack-app.mdx +0 -1
- package/docs/zh/components/other-plugins.mdx +0 -0
- package/docs/zh/components/ssr-monitor.mdx +3 -0
- package/docs/zh/configure/app/auto-load-plugin.mdx +4 -0
- package/docs/zh/configure/app/output/ssg.mdx +49 -139
- package/docs/zh/configure/app/plugins.mdx +2 -2
- package/docs/zh/configure/app/tools/esbuild.mdx +1 -1
- package/docs/zh/configure/app/tools/swc.mdx +1 -1
- package/docs/zh/configure/app/tools/tailwindcss.mdx +1 -1
- package/docs/zh/guides/_meta.json +0 -5
- package/docs/zh/guides/advanced-features/_meta.json +3 -8
- package/docs/zh/guides/advanced-features/bff/_meta.json +1 -1
- package/docs/zh/guides/advanced-features/bff/extend-server.mdx +156 -0
- package/docs/zh/guides/advanced-features/bff/frameworks.mdx +51 -117
- package/docs/zh/guides/advanced-features/bff/function.mdx +69 -59
- package/docs/zh/guides/advanced-features/bff/sdk.mdx +27 -36
- package/docs/zh/guides/advanced-features/build-performance.mdx +6 -21
- package/docs/zh/guides/advanced-features/page-performance/_meta.json +1 -0
- package/docs/zh/guides/advanced-features/rspack-start.mdx +8 -17
- package/docs/zh/guides/basic-features/_meta.json +31 -9
- package/docs/zh/guides/basic-features/alias.mdx +5 -11
- package/docs/zh/guides/basic-features/css/_meta.json +1 -0
- package/docs/zh/guides/basic-features/css/css-in-js.mdx +34 -0
- package/docs/zh/guides/basic-features/css/css.mdx +25 -0
- package/docs/zh/guides/basic-features/{css.mdx → css/tailwindcss.mdx} +3 -64
- package/docs/zh/guides/basic-features/data/data-fetch.mdx +96 -211
- package/docs/zh/guides/basic-features/data/data-write.mdx +54 -55
- package/docs/zh/guides/basic-features/debug/_meta.json +1 -0
- package/docs/zh/guides/basic-features/debug/rsdoctor.mdx +57 -0
- package/docs/zh/guides/{advanced-features → basic-features/debug}/using-storybook.mdx +1 -1
- package/docs/zh/guides/basic-features/env-vars.mdx +1 -1
- package/docs/zh/guides/basic-features/render/_meta.json +1 -0
- package/docs/zh/guides/basic-features/render/ssg.mdx +210 -0
- package/docs/zh/guides/{advanced-features/ssr/cache.mdx → basic-features/render/ssr-cache.mdx} +16 -26
- package/docs/zh/guides/basic-features/render/ssr.mdx +309 -0
- package/docs/zh/guides/{advanced-features/ssr/stream.mdx → basic-features/render/streaming-ssr.mdx} +22 -37
- package/docs/zh/guides/basic-features/routes.mdx +251 -237
- package/docs/zh/guides/basic-features/static-assets/_meta.json +1 -0
- package/docs/zh/guides/basic-features/static-assets.mdx +3 -7
- package/docs/zh/guides/basic-features/testing/_meta.json +1 -0
- package/docs/zh/guides/basic-features/testing/cypress.mdx +95 -0
- package/docs/zh/guides/basic-features/testing/jest.mdx +148 -0
- package/docs/zh/guides/basic-features/testing/playwright.mdx +112 -0
- package/docs/zh/guides/basic-features/testing/vitest.mdx +100 -0
- package/docs/zh/guides/concept/entries.mdx +6 -3
- package/docs/zh/guides/deprecated.md +4 -0
- package/docs/zh/guides/get-started/quick-start.mdx +1 -1
- package/docs/zh/guides/get-started/tech-stack.mdx +8 -8
- package/docs/zh/guides/topic-detail/_meta.json +0 -6
- package/docs/zh/guides/topic-detail/generator/create/config.mdx +0 -10
- package/docs/zh/guides/topic-detail/generator/create/use.mdx +0 -1
- package/docs/zh/plugin/_meta.json +19 -0
- package/docs/zh/plugin/cli-plugins/_meta.json +1 -0
- package/docs/zh/plugin/cli-plugins/plugin-bff.mdx +5 -0
- package/docs/zh/plugin/cli-plugins/plugin-ssg.mdx +5 -0
- package/docs/zh/{guides/rsbuild-plugins → plugin/cli-plugins}/plugin-swc.mdx +7 -0
- package/docs/zh/plugin/cli-plugins/plugin-tailwind.mdx +5 -0
- package/docs/zh/plugin/cli-plugins.mdx +6 -0
- package/docs/zh/{guides/advanced-features/rsbuild-plugin.mdx → plugin/introduction.mdx} +38 -13
- package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/extend.mdx +1 -1
- package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/implement.mdx +3 -3
- package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/plugin-api.mdx +2 -2
- package/docs/zh/plugin/rsbuild-plugins/_meta.json +1 -0
- package/docs/zh/plugin/rsbuild-plugins.mdx +4 -0
- package/docs/zh/tutorials/first-app/c03-css.mdx +1 -1
- package/i18n.json +42 -6
- package/package.json +7 -6
- package/rspress.config.ts +1 -58
- package/src/components/Footer/index.tsx +1 -1
- package/src/pages/index.tsx +0 -1
- package/docs/en/apis/app/hooks/api/api.mdx +0 -80
- package/docs/en/apis/app/hooks/api/app.mdx +0 -12
- package/docs/en/apis/app/hooks/config/storybook.mdx +0 -37
- package/docs/en/guides/advanced-features/bff/type.mdx +0 -46
- package/docs/en/guides/advanced-features/eslint.mdx +0 -148
- package/docs/en/guides/advanced-features/ssg.mdx +0 -116
- package/docs/en/guides/advanced-features/ssr/_meta.json +0 -1
- package/docs/en/guides/advanced-features/ssr/index.mdx +0 -23
- package/docs/en/guides/advanced-features/ssr/stream.mdx +0 -248
- package/docs/en/guides/advanced-features/ssr/usage.mdx +0 -341
- package/docs/en/guides/advanced-features/ssr.mdx +0 -555
- package/docs/zh/apis/app/hooks/api/api.mdx +0 -81
- package/docs/zh/apis/app/hooks/api/app.mdx +0 -12
- package/docs/zh/apis/app/hooks/config/storybook.mdx +0 -38
- package/docs/zh/guides/advanced-features/bff/type.mdx +0 -46
- package/docs/zh/guides/advanced-features/eslint.mdx +0 -152
- package/docs/zh/guides/advanced-features/ssg.mdx +0 -116
- package/docs/zh/guides/advanced-features/ssr/_meta.json +0 -1
- package/docs/zh/guides/advanced-features/ssr/index.mdx +0 -23
- package/docs/zh/guides/advanced-features/ssr/usage.mdx +0 -329
- /package/docs/en/guides/advanced-features/{bff/index.mdx → bff.mdx} +0 -0
- /package/docs/en/guides/advanced-features/{code-split.mdx → page-performance/code-split.mdx} +0 -0
- /package/docs/en/guides/advanced-features/{inline-assets.mdx → page-performance/inline-assets.mdx} +0 -0
- /package/docs/en/guides/advanced-features/{optimize-bundle.mdx → page-performance/optimize-bundle.mdx} +0 -0
- /package/docs/en/guides/basic-features/{mock.mdx → debug/mock.mdx} +0 -0
- /package/docs/en/guides/basic-features/{proxy.mdx → debug/proxy.mdx} +0 -0
- /package/docs/en/guides/basic-features/{json-files.mdx → static-assets/json-files.mdx} +0 -0
- /package/docs/en/guides/basic-features/{svg-assets.mdx → static-assets/svg-assets.mdx} +0 -0
- /package/docs/en/guides/basic-features/{wasm-assets.mdx → static-assets/wasm-assets.mdx} +0 -0
- /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/_meta.json +0 -0
- /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/hook-list.mdx +0 -0
- /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/hook.mdx +0 -0
- /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/introduction.mdx +0 -0
- /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/lifecycle.mdx +0 -0
- /package/docs/en/{guides/topic-detail/framework-plugin → plugin/plugin-system}/relationship.mdx +0 -0
- /package/docs/en/{guides → plugin}/rsbuild-plugins/plugin-esbuild.mdx +0 -0
- /package/docs/zh/guides/advanced-features/{bff/index.mdx → bff.mdx} +0 -0
- /package/docs/zh/guides/advanced-features/{code-split.mdx → page-performance/code-split.mdx} +0 -0
- /package/docs/zh/guides/advanced-features/{inline-assets.mdx → page-performance/inline-assets.mdx} +0 -0
- /package/docs/zh/guides/advanced-features/{optimize-bundle.mdx → page-performance/optimize-bundle.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{css-modules.mdx → css/css-modules.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{mock.mdx → debug/mock.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{proxy.mdx → debug/proxy.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{json-files.mdx → static-assets/json-files.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{svg-assets.mdx → static-assets/svg-assets.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{wasm-assets.mdx → static-assets/wasm-assets.mdx} +0 -0
- /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/_meta.json +0 -0
- /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/hook-list.mdx +0 -0
- /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/hook.mdx +0 -0
- /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/introduction.mdx +0 -0
- /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/lifecycle.mdx +0 -0
- /package/docs/zh/{guides/topic-detail/framework-plugin → plugin/plugin-system}/relationship.mdx +0 -0
- /package/docs/zh/{guides → plugin}/rsbuild-plugins/plugin-esbuild.mdx +0 -0
@@ -1,19 +1,20 @@
|
|
1
1
|
---
|
2
|
-
title: Data writing
|
3
2
|
sidebar_position: 4
|
4
3
|
---
|
5
4
|
|
6
|
-
# Data
|
5
|
+
# Data Writing
|
7
6
|
|
8
|
-
In the Data
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
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
|
-
|
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
|

|
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
|
-
|
82
|
+
### params
|
76
83
|
|
77
|
-
|
78
|
-
|
79
|
-
The traditional state management method will hold the state on the client side and remotely respectively::
|
80
|
-
|
81
|
-

|
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
|
-

|
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
|
-
|
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
|
-
|
113
|
-
|
97
|
+
### request
|
114
98
|
|
115
|
-
|
99
|
+
`request` is an instance of [Fetch Request](https://developer.mozilla.org/en-US/docs/Web/API/Request).
|
116
100
|
|
117
|
-
|
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
|
-
|
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
|
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
|
-
|
118
|
+
### Difference
|
139
119
|
|
140
|
-
|
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
|
160
|
-
|
161
|
-
`action`
|
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
|
-
###
|
146
|
+
### Data Types
|
174
147
|
|
175
148
|
The first parameter of the `submit` function can accept different types of values.
|
176
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
+

|
221
|
+
|
222
|
+
In Modern.js, we aim to help developers automatically synchronize client and server state using Loader and Action:
|
223
|
+
|
224
|
+

|
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
|
228
|
+
## CSR and SSR
|
240
229
|
|
241
|
-
|
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
|
+
:::
|