@modern-js/main-doc 0.0.0-next-1680864210554 → 0.0.0-next-1680878011563
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -2
- package/docs/en/apis/app/commands.mdx +1 -1
- package/docs/en/apis/app/hooks/api/framework/lambda.mdx +2 -2
- package/docs/en/apis/app/hooks/api/functions/api.mdx +3 -3
- package/docs/en/apis/app/hooks/api/functions/app.mdx +1 -1
- package/docs/en/apis/app/hooks/api/test.mdx +2 -1
- package/docs/en/apis/app/hooks/config/mock.mdx +1 -1
- package/docs/en/apis/app/hooks/config/upload.mdx +1 -1
- package/docs/en/apis/app/hooks/server/test.mdx +1 -1
- package/docs/en/apis/app/hooks/src/app.mdx +1 -1
- package/docs/en/apis/app/hooks/src/pages.mdx +1 -1
- package/docs/en/apis/app/runtime/app/define-config.mdx +1 -1
- package/docs/en/apis/app/runtime/core/bootstrap.mdx +2 -2
- package/docs/en/apis/app/runtime/core/use-loader.mdx +2 -2
- package/docs/en/apis/app/runtime/model/auto-actions.mdx +6 -6
- package/docs/en/apis/app/runtime/model/connect.mdx +2 -1
- package/docs/en/apis/app/runtime/model/create-app.mdx +1 -1
- package/docs/en/apis/app/runtime/model/handle-effect.mdx +3 -3
- package/docs/en/apis/app/runtime/model/model_.mdx +2 -2
- package/docs/en/apis/app/runtime/model/use-model.mdx +2 -2
- package/docs/en/apis/app/runtime/model/use-static-model.mdx +2 -2
- package/docs/en/apis/app/runtime/model/use-store.mdx +1 -1
- package/docs/en/apis/app/runtime/router/router.mdx +1 -0
- package/docs/en/apis/app/runtime/ssr/pre-render.mdx +2 -2
- package/docs/en/apis/app/runtime/testing/render.mdx +1 -1
- package/docs/en/components/enable-bff.mdx +2 -2
- package/docs/en/configure/app/output/ssg.mdx +1 -1
- package/docs/en/configure/app/plugins.mdx +3 -3
- package/docs/en/configure/app/tools/swc.mdx +1 -1
- package/docs/en/guides/advanced-features/bff/function.mdx +3 -3
- package/docs/en/guides/advanced-features/code-split.mdx +2 -2
- package/docs/en/guides/advanced-features/eslint.mdx +1 -1
- package/docs/en/guides/advanced-features/ssg.mdx +2 -2
- package/docs/en/guides/basic-features/alias.mdx +1 -1
- package/docs/en/guides/basic-features/env-vars.mdx +5 -5
- package/docs/en/guides/basic-features/routes.mdx +26 -28
- package/docs/en/guides/concept/entries.mdx +3 -3
- package/docs/en/guides/get-started/quick-start.mdx +6 -23
- package/docs/en/guides/get-started/upgrade.mdx +7 -7
- package/docs/en/guides/topic-detail/framework-plugin/hook.mdx +1 -1
- package/docs/en/guides/topic-detail/generator/codesmith/api/json.mdx +3 -3
- package/docs/en/guides/topic-detail/generator/config/app.mdx +1 -1
- package/docs/en/guides/topic-detail/generator/config/monorepo.mdx +1 -1
- package/docs/en/guides/topic-detail/generator/plugin/api/file/addHelper.mdx +1 -1
- package/docs/en/guides/topic-detail/model/manage-effects.mdx +2 -1
- package/docs/en/guides/topic-detail/model/model-communicate.mdx +1 -1
- package/docs/zh/apis/app/hooks/src/pages.mdx +1 -1
- package/docs/zh/apis/app/runtime/model/handle-effect.mdx +2 -1
- package/docs/zh/apis/app/runtime/model/model_.mdx +4 -2
- package/docs/zh/blog/updates/2022-0708-updates.md +1 -2
- package/docs/zh/components/enable-bff.mdx +2 -2
- package/docs/zh/guides/advanced-features/ssr.mdx +15 -20
- package/docs/zh/guides/basic-features/routes.mdx +25 -25
- package/docs/zh/guides/concept/entries.mdx +4 -4
- package/docs/zh/guides/get-started/upgrade.mdx +3 -3
- package/package.json +5 -5
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
title: Routes
|
|
3
3
|
sidebar_position: 1
|
|
4
4
|
---
|
|
5
|
+
|
|
5
6
|
# Routes
|
|
6
7
|
|
|
7
8
|
Modern.js build-in provides partial support for [React Router 6](https://reactrouter.com/en/main) and provides various types of routing modes. According to different [entry](/guides/concept/entries) types, routing is divided into three modes, namely **Conventional routing**, **Self-controlled routing** and **Other**.
|
|
@@ -57,8 +58,8 @@ Similarly, `routes/user/layout.tsx` will be used as a layout component for all c
|
|
|
57
58
|
```tsx
|
|
58
59
|
<Layout>
|
|
59
60
|
<UserLayout>
|
|
60
|
-
<UserPage
|
|
61
|
-
|
|
61
|
+
<UserPage />
|
|
62
|
+
</UserLayout>
|
|
62
63
|
</Layout>
|
|
63
64
|
```
|
|
64
65
|
|
|
@@ -106,8 +107,8 @@ In order to facilitate the introduction of the relationship between `<Layout>` a
|
|
|
106
107
|
```tsx
|
|
107
108
|
<Layout>
|
|
108
109
|
<UserLayout>
|
|
109
|
-
<UserPage
|
|
110
|
-
|
|
110
|
+
<UserPage />
|
|
111
|
+
</UserLayout>
|
|
111
112
|
</Layout>
|
|
112
113
|
```
|
|
113
114
|
|
|
@@ -158,10 +159,9 @@ The `routes/$.tsx` component is rendered when accessing any path that does not m
|
|
|
158
159
|
import { useParams } from '@modern-js/runtime/router';
|
|
159
160
|
// When the path is `/aaa/bbb`
|
|
160
161
|
const params = useParams();
|
|
161
|
-
params['*']
|
|
162
|
+
params['*']; // => 'aaa/bbb'
|
|
162
163
|
```
|
|
163
164
|
|
|
164
|
-
|
|
165
165
|
### Layout with No Path
|
|
166
166
|
|
|
167
167
|
When a directory name begins with `__`, the corresponding directory name is not converted to the actual routing path, such as the following file directory:
|
|
@@ -230,15 +230,15 @@ When a route jumps from `/` to `/blog`, if the JS Chunk of the `<Blog>` componen
|
|
|
230
230
|
You can redirect routes by creating a [`data loader`](/guides/basic-features/data-fetch) file, Suppose you have the file `routes/user/page.tsx` and you want to redirect the route corresponding to this file, you can create the file `routes/user/page.loader.ts`:
|
|
231
231
|
|
|
232
232
|
```ts title="routes/user/page.loader.ts"
|
|
233
|
-
import { redirect } from '@modern-js/runtime/router'
|
|
233
|
+
import { redirect } from '@modern-js/runtime/router';
|
|
234
234
|
|
|
235
235
|
export default () => {
|
|
236
236
|
const user = await getUser();
|
|
237
|
-
if(!user){
|
|
237
|
+
if (!user) {
|
|
238
238
|
return redirect('/login');
|
|
239
239
|
}
|
|
240
240
|
return null;
|
|
241
|
-
}
|
|
241
|
+
};
|
|
242
242
|
```
|
|
243
243
|
|
|
244
244
|
### ErrorBoundary
|
|
@@ -255,15 +255,15 @@ Within the `<ErrorBoundary>` component, you can use [useRouteError](/apis/app/ru
|
|
|
255
255
|
|
|
256
256
|
```tsx
|
|
257
257
|
import { useRouteError } from '@modern-js/runtime/router';
|
|
258
|
-
export
|
|
258
|
+
export const ErrorBoundary = () => {
|
|
259
259
|
const error = useRouteError();
|
|
260
260
|
return (
|
|
261
261
|
<div>
|
|
262
|
-
|
|
263
|
-
|
|
262
|
+
<h1>{error.status}</h1>
|
|
263
|
+
<h2>{error.message}</h2>
|
|
264
264
|
</div>
|
|
265
|
-
)
|
|
266
|
-
}
|
|
265
|
+
);
|
|
266
|
+
};
|
|
267
267
|
```
|
|
268
268
|
|
|
269
269
|
### Hooks before rendering
|
|
@@ -286,15 +286,13 @@ This feature is useful when the application requires pre-page data, custom data
|
|
|
286
286
|
:::
|
|
287
287
|
|
|
288
288
|
```ts title="src/routes/layout.tsx"
|
|
289
|
-
import {
|
|
290
|
-
RuntimeContext,
|
|
291
|
-
} from '@modern-js/runtime';
|
|
289
|
+
import { RuntimeContext } from '@modern-js/runtime';
|
|
292
290
|
|
|
293
291
|
export const init = (context: RuntimeContext) => {
|
|
294
292
|
return {
|
|
295
293
|
message: 'Hello World',
|
|
296
|
-
}
|
|
297
|
-
}
|
|
294
|
+
};
|
|
295
|
+
};
|
|
298
296
|
```
|
|
299
297
|
|
|
300
298
|
```tsx title="src/routes/page.tsx"
|
|
@@ -305,7 +303,7 @@ export default () => {
|
|
|
305
303
|
const { message } = context.getInitData();
|
|
306
304
|
|
|
307
305
|
return <div>{message}</div>;
|
|
308
|
-
}
|
|
306
|
+
};
|
|
309
307
|
```
|
|
310
308
|
|
|
311
309
|
When working with SSR, the browser side can get the data returned by `init` during SSR, and the developer can decide whether to retrieve the data on the browser side to overwrite the SSR data, for example:
|
|
@@ -317,18 +315,18 @@ export const init = (context: RuntimeContext) => {
|
|
|
317
315
|
if (process.env.MODERN_TARGET === 'node') {
|
|
318
316
|
return {
|
|
319
317
|
message: 'Hello World By Server',
|
|
320
|
-
}
|
|
318
|
+
};
|
|
321
319
|
} else {
|
|
322
320
|
const { context } = runtimeContext;
|
|
323
321
|
const data = context.getInitData();
|
|
324
322
|
// If do not get the expected data
|
|
325
323
|
if (!data.message) {
|
|
326
324
|
return {
|
|
327
|
-
message: 'Hello World By Client'
|
|
328
|
-
}
|
|
325
|
+
message: 'Hello World By Client',
|
|
326
|
+
};
|
|
329
327
|
}
|
|
330
328
|
}
|
|
331
|
-
}
|
|
329
|
+
};
|
|
332
330
|
```
|
|
333
331
|
|
|
334
332
|
### Runtime Configuration
|
|
@@ -341,9 +339,9 @@ import type { AppConfig } from '@modern-js/runtime';
|
|
|
341
339
|
export const config = (): AppConfig => {
|
|
342
340
|
return {
|
|
343
341
|
router: {
|
|
344
|
-
supportHtml5History: false
|
|
345
|
-
}
|
|
346
|
-
}
|
|
342
|
+
supportHtml5History: false,
|
|
343
|
+
},
|
|
344
|
+
};
|
|
347
345
|
};
|
|
348
346
|
```
|
|
349
347
|
|
|
@@ -367,7 +365,7 @@ export default () => {
|
|
|
367
365
|
```
|
|
368
366
|
|
|
369
367
|
:::note
|
|
370
|
-
Modern.js has a series of resource loading and rendering optimizations to the default convention-based routing, and provides out-of-the-box SSR capabilities,
|
|
368
|
+
Modern.js has a series of resource loading and rendering optimizations to the default convention-based routing, and provides out-of-the-box SSR capabilities, when using self-directed routing, need to be packaged by the developer, and it is recommended that developers use convention-based routing.
|
|
371
369
|
|
|
372
370
|
:::
|
|
373
371
|
|
|
@@ -132,9 +132,9 @@ The content of the file generated by Modern.js is as follows:
|
|
|
132
132
|
```js
|
|
133
133
|
import React from 'react';
|
|
134
134
|
import ReactDOM from 'react-dom/client';
|
|
135
|
-
import customBootstrap from '@
|
|
136
|
-
import App from '@
|
|
137
|
-
import { router, state } from '@
|
|
135
|
+
import customBootstrap from '@_modern_js_src/index.tsx';
|
|
136
|
+
import App from '@_modern_js_src/App';
|
|
137
|
+
import { router, state } from '@modern-js/runtime/plugins';
|
|
138
138
|
|
|
139
139
|
const IS_BROWSER = typeof window !== 'undefined' && window.name !== 'nodejs';
|
|
140
140
|
const MOUNT_ID = 'root';
|
|
@@ -7,39 +7,22 @@ sidebar_position: 2
|
|
|
7
7
|
|
|
8
8
|
## Environment
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
import Prerequisites from "@site-docs-en/components/prerequisites"
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
Modern.js recommend installing [nvm](https://github.com/nvm-sh/nvm#install--update-script) in the development environment and integrating [script to automatically switch node versions](https://github.com/nvm-sh/nvm#deeper-shell-integration) in the shell.
|
|
15
|
-
|
|
16
|
-
Then there is a `.nvmrc` file with the content of `lts/fermium` or `lts/gallium` in the root directory of the repository, it will automatically install or switch to the correct Node.js version when entering the repository.
|
|
17
|
-
|
|
18
|
-
### pnpm
|
|
19
|
-
|
|
20
|
-
[pnpm](https://pnpm.io/installation) is recommended for package management.
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
npm install -g pnpm@7
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
:::note
|
|
27
|
-
Modern.js also supports other package managers, such as `yarn` or `npm`.
|
|
28
|
-
|
|
29
|
-
:::
|
|
12
|
+
<Prerequisites />
|
|
30
13
|
|
|
31
14
|
## Installation
|
|
32
15
|
|
|
33
|
-
Modern.js provides the `@modern-js/create` tool
|
|
16
|
+
Modern.js provides the `@modern-js/create` tool for creating new projects. You can use `npx` to run it.
|
|
34
17
|
|
|
35
|
-
|
|
18
|
+
You can create the project in an existing empty directory:
|
|
36
19
|
|
|
37
20
|
```bash
|
|
38
21
|
mkdir myapp && cd myapp
|
|
39
22
|
npx @modern-js/create
|
|
40
23
|
```
|
|
41
24
|
|
|
42
|
-
|
|
25
|
+
You can also directly create the project as a new folder:
|
|
43
26
|
|
|
44
27
|
```bash
|
|
45
28
|
npx @modern-js/create myapp
|
|
@@ -161,4 +144,4 @@ Open http://localhost:8000/ in the browser and the content should be the same as
|
|
|
161
144
|
|
|
162
145
|
## Deploy
|
|
163
146
|
|
|
164
|
-
|
|
147
|
+
Once the local verification is complete, the outputs under `dist` folder can be organized into the structure required by the server for deployment.
|
|
@@ -25,24 +25,24 @@ You can see that the dependency in the project `package.json` has been changed t
|
|
|
25
25
|
|
|
26
26
|
## Specify version upgrade
|
|
27
27
|
|
|
28
|
-
Modern.js
|
|
28
|
+
All packages of Modern.js are published using the **unified version number**.
|
|
29
29
|
|
|
30
|
-
According to the website
|
|
30
|
+
According to the website release note, developers can also manually upgrade the project to the desired version.
|
|
31
31
|
|
|
32
32
|
:::tip
|
|
33
33
|
When upgrading, you need to upgrade to all packages provided by the Modern.js, rather than upgrading a single dependency.
|
|
34
34
|
|
|
35
35
|
:::
|
|
36
36
|
|
|
37
|
-
##
|
|
37
|
+
## Lock nested dependency
|
|
38
38
|
|
|
39
|
-
When there is a problem with one of the
|
|
39
|
+
When there is a problem with one of the nested dependencies of the project, and the Modern.js cannot be updated immediately, you can use the package manager to lock the child dependency version.
|
|
40
40
|
|
|
41
41
|
### pnpm
|
|
42
42
|
|
|
43
43
|
For projects using pnpm, add the following configuration to the `package.json` in the **project root directory** and re-execute `pnpm install`:
|
|
44
44
|
|
|
45
|
-
```json
|
|
45
|
+
```json title="package.json"
|
|
46
46
|
{
|
|
47
47
|
"pnpm": {
|
|
48
48
|
"overrides": {
|
|
@@ -56,7 +56,7 @@ For projects using pnpm, add the following configuration to the `package.json` i
|
|
|
56
56
|
|
|
57
57
|
For projects using Yarn, add the following configuration to the `package.json` in the **project root directory** and re-execute `yarn install`:
|
|
58
58
|
|
|
59
|
-
```json
|
|
59
|
+
```json title="package.json"
|
|
60
60
|
{
|
|
61
61
|
"resolutions": {
|
|
62
62
|
"package-name": "^1.0.0"
|
|
@@ -68,7 +68,7 @@ For projects using Yarn, add the following configuration to the `package.json` i
|
|
|
68
68
|
|
|
69
69
|
For projects using Npm, add the following configuration to the `package.json` in the **project root directory** and re-execute `npm install`:
|
|
70
70
|
|
|
71
|
-
```json
|
|
71
|
+
```json title="package.json"
|
|
72
72
|
{
|
|
73
73
|
"overrides": {
|
|
74
74
|
"package-name": "^1.0.0"
|
|
@@ -32,7 +32,7 @@ pipeline.run(1); // 4
|
|
|
32
32
|
pipeline.run(5); // 12
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
In this example, a `Pipeline<number, number>` is created on line 3. This means that when you run it, you need to pass in a `number`, and you will get a `number` as a result
|
|
35
|
+
In this example, a `Pipeline<number, number>` is created on line 3. This means that when you run it, you need to pass in a `number`, and you will get a `number` as a result, the type is:
|
|
36
36
|
|
|
37
37
|
```ts
|
|
38
38
|
(count: number, next: (nextCount: number) => number) => number;
|
|
@@ -35,7 +35,7 @@ Get the JSON file content.
|
|
|
35
35
|
|
|
36
36
|
Parameter:
|
|
37
37
|
|
|
38
|
-
- resource: `FsResource`. A file resource
|
|
38
|
+
- resource: `FsResource`. A file resource, get by `context.materials.default.get(<filename>)`.
|
|
39
39
|
|
|
40
40
|
### extend
|
|
41
41
|
|
|
@@ -43,7 +43,7 @@ Merge objects into a JSON file.
|
|
|
43
43
|
|
|
44
44
|
Parameter:
|
|
45
45
|
|
|
46
|
-
- resource: `FsResource`. A file resource
|
|
46
|
+
- resource: `FsResource`. A file resource, get by `context.materials.default.get(<filename>)`.
|
|
47
47
|
- obj: `Record<string, any>`. Object to be merged.
|
|
48
48
|
|
|
49
49
|
### update
|
|
@@ -52,5 +52,5 @@ pdate object fields to JSON file.
|
|
|
52
52
|
|
|
53
53
|
Parameter:
|
|
54
54
|
|
|
55
|
-
- resource: `FsResource`. A file resource
|
|
55
|
+
- resource: `FsResource`. A file resource, get by `context.materials.default.get(<filename>)`.
|
|
56
56
|
- operation: `{ query: Record<string, any>; update: Record<string, any> }`. Update operation, use gesture to view [declaration-update](https://www.npmjs.com/package/declaration-update) in detail.
|
|
@@ -12,7 +12,7 @@ The Monorepo project supports the creation of sub-projects by using the new comm
|
|
|
12
12
|
|
|
13
13
|
### solution
|
|
14
14
|
|
|
15
|
-
Subproject type(solution)
|
|
15
|
+
Subproject type(solution), the different subproject type fields are:
|
|
16
16
|
|
|
17
17
|
- Application (mwa)
|
|
18
18
|
- Application (Test) (mwa_test)
|
|
@@ -4,7 +4,7 @@ sidebar_position: 2
|
|
|
4
4
|
|
|
5
5
|
# addHelper
|
|
6
6
|
|
|
7
|
-
For text files, add a customized Help function of Handlebars
|
|
7
|
+
For text files, add a customized Help function of Handlebars, the specific viewable document[Custom Helpers](https://handlebarsjs.com/guide/#custom-helpers).
|
|
8
8
|
|
|
9
9
|
This method is available on the `onForged` time to live API parameter.
|
|
10
10
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
sidebar_position: 5
|
|
3
3
|
title: Management Effect
|
|
4
4
|
---
|
|
5
|
+
|
|
5
6
|
# Management Effect
|
|
6
7
|
|
|
7
8
|
The actions in the model must be pure functions and cannot have any side effects during execution. However, in real-world scenarios, we often encounter many side effects, such as: requesting data from an HTTP API to obtain state data, or modifying `localStorage` or sending events while updating the state. In Reduck, side effects are managed through the model's `effects` function.
|
|
@@ -88,7 +89,7 @@ For this type of side effect scenario, `handleEffect` stipulates that the state
|
|
|
88
89
|
{
|
|
89
90
|
result: null,
|
|
90
91
|
error: null,
|
|
91
|
-
pending: false
|
|
92
|
+
pending: false,
|
|
92
93
|
}
|
|
93
94
|
```
|
|
94
95
|
|
|
@@ -85,7 +85,7 @@ pages 目录下的文件满足以下条件的不会被当做路由文件
|
|
|
85
85
|
import React from 'react';
|
|
86
86
|
import UserLayout from 'xxxx';
|
|
87
87
|
|
|
88
|
-
export
|
|
88
|
+
export const App = ({Component, ...pageProps}:{ Component: React.ComponentType}) => {
|
|
89
89
|
return (
|
|
90
90
|
<UserLayout>
|
|
91
91
|
<Component {...pageProps} />
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
sidebar_position: 1
|
|
3
3
|
title: model
|
|
4
4
|
---
|
|
5
|
+
|
|
5
6
|
# model
|
|
6
7
|
|
|
7
|
-
import ReduckTip from
|
|
8
|
+
import ReduckTip from '@site-docs/components/reduck-tip';
|
|
8
9
|
|
|
9
10
|
<ReduckTip />
|
|
10
11
|
|
|
@@ -61,7 +62,8 @@ const fooModel = model('foo').define({
|
|
|
61
62
|
- context: Context,Reduck 上下文对象,可以获取底层的 `store` 对象。`store` 除支持 Redux Store 的所有 [API](https://redux.js.org/api/store) 以外,还挂载了用于消费 Model 的 `use` 的方法,和用于卸载 Model 的 `unmount` 方法。
|
|
62
63
|
- utils: Utils,定义 Model 时,常用的工具函数:`use`、`onMount`。`use` 作用同 `store` 对象上的 `use`,`onMount` 是 Model 挂载后的钩子函数。
|
|
63
64
|
|
|
64
|
-
{/* TODO: @anchao 调整类型
|
|
65
|
+
{/* TODO: @anchao 调整类型 */}
|
|
66
|
+
|
|
65
67
|
```ts
|
|
66
68
|
interface Utils {
|
|
67
69
|
use: UseModel;
|
|
@@ -39,8 +39,7 @@ npx @modern-js/upgrade
|
|
|
39
39
|
|
|
40
40
|
新的模块工程项目,不仅支持对产物做 bundless 构建,也支持 bundle 构建。通过配置 `buildConfig` 下的 [`buildType`](https://modernjs.dev/v1/docs/apis/module/config/output/build-config/build-type) ,即可进行 bundle 构建:
|
|
41
41
|
|
|
42
|
-
```ts
|
|
43
|
-
// modern.config.ts
|
|
42
|
+
```ts title="modern.config.ts"
|
|
44
43
|
import { defineConfig } from '@modern-js/module-tools';
|
|
45
44
|
|
|
46
45
|
export default defineConfig({
|
|
@@ -6,7 +6,7 @@ import { Tabs, Tab as TabItem } from "@theme";
|
|
|
6
6
|
<Tabs>
|
|
7
7
|
<TabItem value="express" label="Express.js" default>
|
|
8
8
|
|
|
9
|
-
```ts title="
|
|
9
|
+
```ts title="modern.config.ts"
|
|
10
10
|
import expressPlugin from '@modern-js/plugin-express';
|
|
11
11
|
import bffPlugin from '@modern-js/plugin-bff';
|
|
12
12
|
|
|
@@ -18,7 +18,7 @@ export default defineConfig({
|
|
|
18
18
|
</TabItem>
|
|
19
19
|
<TabItem value="koa" label="Koa.js">
|
|
20
20
|
|
|
21
|
-
```ts title="
|
|
21
|
+
```ts title="modern.config.ts"
|
|
22
22
|
import koaPlugin from '@modern-js/plugin-koa';
|
|
23
23
|
import bffPlugin from '@modern-js/plugin-bff';
|
|
24
24
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
title: 服务端渲染(SSR)
|
|
3
3
|
sidebar_position: 3
|
|
4
4
|
---
|
|
5
|
+
|
|
5
6
|
# 服务端渲染(SSR)
|
|
6
7
|
|
|
7
8
|
在 Modern.js 中,SSR 也是开箱即用的。开发者无需为 SSR 编写复杂的服务端逻辑,也无需关心 SSR 的运维,或是创建单独的服务。Modern.js 拥有完备的 SSR 降级策略,保证页面能够安全运行。
|
|
@@ -12,10 +13,10 @@ sidebar_position: 3
|
|
|
12
13
|
import { defineConfig } from '@modern-js/app-tools';
|
|
13
14
|
|
|
14
15
|
export default defineConfig({
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
server: {
|
|
17
|
+
ssr: true,
|
|
17
18
|
},
|
|
18
|
-
})
|
|
19
|
+
});
|
|
19
20
|
```
|
|
20
21
|
|
|
21
22
|
## SSR 时的数据获取
|
|
@@ -33,7 +34,7 @@ export default () => {
|
|
|
33
34
|
在组件中可以通过 Hooks API 的方式获取 `loader` 函数返回的数据:
|
|
34
35
|
|
|
35
36
|
```tsx
|
|
36
|
-
import { useLoaderData } from '@modern-js/runtime/router'
|
|
37
|
+
import { useLoaderData } from '@modern-js/runtime/router';
|
|
37
38
|
export default () => {
|
|
38
39
|
const data = useLoaderData();
|
|
39
40
|
return <div>{data.message}</div>;
|
|
@@ -45,14 +46,13 @@ Modern.js 打破传统的 SSR 开发模式,提供了用户无感的 SSR 开发
|
|
|
45
46
|
不过,开发者仍然需要关注数据的兜底处理,例如 `null` 值或不符合预期的数据返回。避免在 SSR 时产生 React 渲染错误或是返回凌乱的渲染结果。
|
|
46
47
|
|
|
47
48
|
:::info 补充信息
|
|
49
|
+
|
|
48
50
|
1. 当以客户端路由的方式请求页面时,Modern.js 会发送一个 HTTP 请求,服务端接收到请求后执行页面对应的 Data Loader 函数,然后将执行结果作为请求的响应返回浏览器。
|
|
49
51
|
|
|
50
52
|
2. 使用 Data Loader 时,数据获取发生在渲染前,Modern.js 也仍然支持在组件渲染时获取数据。更多相关内容可以查看[数据获取](/guides/basic-features/data-fetch)。
|
|
51
53
|
|
|
52
54
|
:::
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
|
|
56
56
|
## 保持渲染一致
|
|
57
57
|
|
|
58
58
|
有些业务中,通常需要根据当前的运行容器环境特征做不同的 UI 展示,例如 [UA](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent) 信息。如果处理不够仔细,此时很有可能出现不符合预期的渲染结果。
|
|
@@ -291,12 +291,12 @@ Modern.js 支持了 React 18 的流式渲染,可以通过如下配置启用:
|
|
|
291
291
|
import { defineConfig } from '@modern-js/app-tools';
|
|
292
292
|
|
|
293
293
|
export default defineConfig({
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
294
|
+
server: {
|
|
295
|
+
ssr: {
|
|
296
|
+
mode: 'stream',
|
|
297
297
|
},
|
|
298
298
|
},
|
|
299
|
-
})
|
|
299
|
+
});
|
|
300
300
|
```
|
|
301
301
|
|
|
302
302
|
Modern.js 的流式渲染基于 React Router 实现,主要涉及 API 有:
|
|
@@ -305,7 +305,6 @@ Modern.js 的流式渲染基于 React Router 实现,主要涉及 API 有:
|
|
|
305
305
|
- [`Await`](https://reactrouter.com/en/main/components/await):用于渲染 Data Loader 返回的异步数据。
|
|
306
306
|
- [`useAsyncValue`](https://reactrouter.com/en/main/hooks/use-async-value):用于从最近的父级 `Await` 组件中获取数据。
|
|
307
307
|
|
|
308
|
-
|
|
309
308
|
### 异步获取数据
|
|
310
309
|
|
|
311
310
|
```ts title='page.loader.ts'
|
|
@@ -334,7 +333,6 @@ export default ({ params }: LoaderFunctionArgs) => {
|
|
|
334
333
|
|
|
335
334
|
return defer({ data: user });
|
|
336
335
|
};
|
|
337
|
-
|
|
338
336
|
```
|
|
339
337
|
|
|
340
338
|
`user` 是一个 Promise 类型的对象,表示需要异步获取的数据,通过 `defer` 处理需要异步获取的 `user`。注意,`defer` 必须接收一个对象类型的参数,
|
|
@@ -343,7 +341,6 @@ export default ({ params }: LoaderFunctionArgs) => {
|
|
|
343
341
|
`defer` 还可以同时接收异步数据和同步数据。例如:
|
|
344
342
|
|
|
345
343
|
```ts title='page.loader.ts'
|
|
346
|
-
|
|
347
344
|
// 省略部分代码
|
|
348
345
|
|
|
349
346
|
export default ({ params }: LoaderFunctionArgs) => {
|
|
@@ -366,15 +363,13 @@ export default ({ params }: LoaderFunctionArgs) => {
|
|
|
366
363
|
|
|
367
364
|
return defer({
|
|
368
365
|
data: user,
|
|
369
|
-
other: await otherData
|
|
366
|
+
other: await otherData,
|
|
370
367
|
});
|
|
371
368
|
};
|
|
372
|
-
|
|
373
369
|
```
|
|
374
370
|
|
|
375
371
|
`otherData` 前加了 `await`,所以是同步获取的数据,它可以和异步获取的数据 `user` 同时传入 `defer`。
|
|
376
372
|
|
|
377
|
-
|
|
378
373
|
### 渲染异步数据
|
|
379
374
|
|
|
380
375
|
通过 `Await` 组件,可以获取到 Data Loader 中异步返回的数据,然后进行渲染。例如:
|
|
@@ -392,7 +387,7 @@ const Page = () => {
|
|
|
392
387
|
User info:
|
|
393
388
|
<Suspense fallback={<div id="loading">loading user data ...</div>}>
|
|
394
389
|
<Await resolve={data.data}>
|
|
395
|
-
{
|
|
390
|
+
{user => {
|
|
396
391
|
return (
|
|
397
392
|
<div id="data">
|
|
398
393
|
name: {user.name}, age: {user.age}
|
|
@@ -430,11 +425,11 @@ const UserInfo = () => {
|
|
|
430
425
|
const user = useAsyncValue();
|
|
431
426
|
|
|
432
427
|
return (
|
|
433
|
-
|
|
428
|
+
<div>
|
|
434
429
|
name: {user.name}, age: {user.age}
|
|
435
430
|
</div>
|
|
436
|
-
)
|
|
437
|
-
}
|
|
431
|
+
);
|
|
432
|
+
};
|
|
438
433
|
|
|
439
434
|
const Page = () => {
|
|
440
435
|
const data = useLoaderData() as Data;
|