@modern-js/main-doc 2.20.0 → 2.21.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +11 -0
- package/docs/en/apis/app/runtime/router/router.mdx +22 -0
- package/docs/en/configure/app/security/nonce.mdx +13 -0
- package/docs/en/guides/advanced-features/rspack-start.mdx +38 -0
- package/docs/en/guides/basic-features/css.mdx +37 -27
- package/docs/en/guides/basic-features/data-fetch.mdx +56 -69
- package/docs/en/guides/basic-features/routes.mdx +189 -93
- package/docs/en/guides/topic-detail/framework-plugin/hook-list.mdx +22 -4
- package/docs/zh/apis/app/runtime/router/router.mdx +22 -0
- package/docs/zh/configure/app/security/nonce.mdx +13 -0
- package/docs/zh/guides/advanced-features/rspack-start.mdx +37 -0
- package/docs/zh/guides/basic-features/data-fetch.mdx +14 -14
- package/docs/zh/guides/basic-features/routes.mdx +22 -22
- package/docs/zh/guides/topic-detail/framework-plugin/hook-list.mdx +23 -5
- package/package.json +7 -7
@@ -5,20 +5,19 @@ sidebar_position: 1
|
|
5
5
|
|
6
6
|
# Routes
|
7
7
|
|
8
|
-
Modern.js
|
8
|
+
Modern.js's routing is based on [React Router 6](https://reactrouter.com/en/main) and provides multiple types of routing modes. According to different [entry](/guides/concept/entries) types, routing is divided into three modes: **Conventional Routing**, **Self-controlled Routing**, and **Other**.
|
9
9
|
|
10
10
|
:::note
|
11
|
-
The
|
12
|
-
|
11
|
+
The routing mentioned in this section refers to client-side routing, i.e., SPA routing.
|
13
12
|
:::
|
14
13
|
|
15
|
-
## Conventional
|
14
|
+
## Conventional Routing
|
16
15
|
|
17
|
-
With `routes/` as the
|
16
|
+
With `routes/` as the convention for entry points, Modern.js automatically generates the corresponding routing structure based on the file system.
|
18
17
|
|
19
|
-
Modern.js supports the popular
|
18
|
+
Modern.js supports the popular conventional routing mode in the industry: **Nested Routing**. When using nested routing, the page's routing corresponds to the UI structure, and we will introduce this routing mode in detail.
|
20
19
|
|
21
|
-
```
|
20
|
+
```bash
|
22
21
|
/user/johnny/profile /user/johnny/posts
|
23
22
|
+------------------+ +-----------------+
|
24
23
|
| User | | User |
|
@@ -29,11 +28,30 @@ Modern.js supports the popular convention routing mode in the industry: **nested
|
|
29
28
|
+------------------+ +-----------------+
|
30
29
|
```
|
31
30
|
|
32
|
-
### Routing
|
31
|
+
### Routing File Convention
|
33
32
|
|
34
|
-
|
33
|
+
Under the `routes/` directory, the directory name is mapped to the route URL. Modern.js has two file conventions, `layout.[jt]sx` and `page.[jt]sx` (abbreviated as`.tsx`). These two files determine the layout structure of the application. `layout.tsx` is used as the layout component, and `page.tsx` acts as the content component, which is the leaf node of the entire route (a route has only one leaf node and must end with a leaf node).
|
35
34
|
|
36
|
-
For example,
|
35
|
+
For example, the following directory structure:
|
36
|
+
|
37
|
+
```bash
|
38
|
+
.
|
39
|
+
└── routes
|
40
|
+
├── page.tsx
|
41
|
+
└── user
|
42
|
+
└── page.tsx
|
43
|
+
```
|
44
|
+
|
45
|
+
This will generate the following two routes:
|
46
|
+
|
47
|
+
- `/`
|
48
|
+
- `/user`
|
49
|
+
|
50
|
+
When `layout.tsx` is added, assuming the following directory:
|
51
|
+
|
52
|
+
:::info
|
53
|
+
Here, `routes/layout.tsx` will be used as the layout component for all components under the `/` route, and `routes/user/layout.tsx` will be used as the layout component for all route components under the `/user` route.
|
54
|
+
:::
|
37
55
|
|
38
56
|
```bash
|
39
57
|
.
|
@@ -45,7 +63,7 @@ For example, here `routes/layout.tsx` will be used as the layout component of al
|
|
45
63
|
└── page.tsx
|
46
64
|
```
|
47
65
|
|
48
|
-
When the route is `/`,
|
66
|
+
When the route is `/`, the following UI layout will be displayed:
|
49
67
|
|
50
68
|
```tsx
|
51
69
|
<Layout>
|
@@ -53,7 +71,7 @@ When the route is `/`, there will be the following UI layout:
|
|
53
71
|
</Layout>
|
54
72
|
```
|
55
73
|
|
56
|
-
Similarly, `routes/user/layout.tsx` will be used as
|
74
|
+
Similarly, `routes/user/layout.tsx` will be used as the layout component for all components under the `/user` route. When the route is `/user`, the following UI layout will be displayed:
|
57
75
|
|
58
76
|
```tsx
|
59
77
|
<Layout>
|
@@ -65,14 +83,26 @@ Similarly, `routes/user/layout.tsx` will be used as a layout component for all c
|
|
65
83
|
|
66
84
|
#### Layout
|
67
85
|
|
68
|
-
`<Layout>` component refers to all `layout.tsx` files
|
86
|
+
The `<Layout>` component refers to all `layout.tsx` files under the `routes/` directory. They represent the layout of the corresponding route segment and use `<Outlet>` to represent child components.
|
87
|
+
|
88
|
+
```tsx title=routes/layout.tsx
|
89
|
+
import { Link, Outlet, useLoaderData } from '@modern-js/runtime/router';
|
90
|
+
|
91
|
+
export default () => {
|
92
|
+
return (
|
93
|
+
<>
|
94
|
+
<Outlet></Outlet>
|
95
|
+
</>
|
96
|
+
);
|
97
|
+
};
|
98
|
+
```
|
69
99
|
|
70
100
|
:::note
|
71
|
-
`<Outlet>` is a new API in React Router 6,
|
101
|
+
`<Outlet>` is a new API in React Router 6. For more details, please refer to [Outlet](https://reactrouter.com/en/main/components/outlet#outlet).
|
72
102
|
|
73
103
|
:::
|
74
104
|
|
75
|
-
|
105
|
+
To simplify the introduction of the relationship between `<Layout>` and `<Outlet>`, the following file directory is used as an example:
|
76
106
|
|
77
107
|
```bash
|
78
108
|
.
|
@@ -86,7 +116,7 @@ In order to facilitate the introduction of the relationship between `<Layout>` a
|
|
86
116
|
└── page.tsx
|
87
117
|
```
|
88
118
|
|
89
|
-
1. When the route is `/`, `<Outlet>` in `routes/layout.tsx` represents the component exported in `routes/page.tsx`, generating the following UI structure:
|
119
|
+
1. When the route is `/`, the `<Outlet>` in `routes/layout.tsx` represents the component exported in `routes/page.tsx`, generating the following UI structure:
|
90
120
|
|
91
121
|
```tsx
|
92
122
|
<Layout>
|
@@ -94,7 +124,7 @@ In order to facilitate the introduction of the relationship between `<Layout>` a
|
|
94
124
|
</Layout>
|
95
125
|
```
|
96
126
|
|
97
|
-
2. When the route is `/blog`, `<Outlet>` in `routes/layout.tsx` represents the component exported in `routes/blog/page.tsx`, generating the following UI structure:
|
127
|
+
2. When the route is `/blog`, the `<Outlet>` in `routes/layout.tsx` represents the component exported in `routes/blog/page.tsx`, generating the following UI structure:
|
98
128
|
|
99
129
|
```tsx
|
100
130
|
<Layout>
|
@@ -102,7 +132,7 @@ In order to facilitate the introduction of the relationship between `<Layout>` a
|
|
102
132
|
</Layout>
|
103
133
|
```
|
104
134
|
|
105
|
-
3. When the route is `/user`, `<Outlet>` in `routes/layout.tsx` represents the component exported in `routes/user/layout.tsx`. `<Outlet>` in `routes/user/layout.tsx` represents the component exported in `routes/user/page.tsx
|
135
|
+
3. When the route is `/user`, the `<Outlet>` in `routes/layout.tsx` represents the component exported in `routes/user/layout.tsx`. The `<Outlet>` in `routes/user/layout.tsx` represents the component exported in `routes/user/page.tsx`, generating the following UI structure:
|
106
136
|
|
107
137
|
```tsx
|
108
138
|
<Layout>
|
@@ -111,18 +141,17 @@ In order to facilitate the introduction of the relationship between `<Layout>` a
|
|
111
141
|
</UserLayout>
|
112
142
|
</Layout>
|
113
143
|
```
|
114
|
-
|
115
|
-
In summary, if there is a `layout.tsx` in the file directory of the subroute, the `<Outlet>` in the previous `layout.tsx` is the `layout.tsx` under the file directory of the subroute, otherwise it is the `page.tsx` under the file directory of the subroute.
|
144
|
+
In summary, if there is a `layout.tsx` file under the sub-route's file directory, the `<Outlet>` in the parent `layout.tsx` will represent the `layout.tsx` in the sub-route file directory. Otherwise, it will represent the `page.tsx` in the sub-route file directory.
|
116
145
|
|
117
146
|
#### Page
|
118
147
|
|
119
|
-
All routes should end with the `<Page>` component.
|
148
|
+
All routes should end with the `<Page>` component. If the developer introduces the `<Outlet>` component in the `page.tsx` file, there will be no effect.
|
120
149
|
|
121
|
-
### Dynamic
|
150
|
+
### Dynamic Routing
|
122
151
|
|
123
|
-
|
152
|
+
Routes generated from file directories named with `[]` will be handled as dynamic routes. For example, the following file directory:
|
124
153
|
|
125
|
-
```
|
154
|
+
```bash
|
126
155
|
└── routes
|
127
156
|
├── [id]
|
128
157
|
│ └── page.tsx
|
@@ -131,21 +160,43 @@ With a file directory named `[]`, the generated route will be used as a dynamic
|
|
131
160
|
└── page.tsx
|
132
161
|
```
|
133
162
|
|
134
|
-
The `routes/[id]/page.tsx` file
|
163
|
+
The `routes/[id]/page.tsx` file will be converted to the `/:id` route. Except for the exact matching `/blog` route, all other `/xxx` routes will match this route.
|
164
|
+
|
165
|
+
In the component, you can use [useParams](/apis/app/runtime/router/router#useparams) to get the corresponding named parameter.
|
166
|
+
|
167
|
+
In the loader, params will be passed as the input parameter of the [loader function](/guides/basic-features/data-fetch#loader-function), and you can get the parameter value through `params.xxx`.
|
168
|
+
|
169
|
+
### Dynamic Optional Routing
|
170
|
+
|
171
|
+
Routes generated from file directories named with `[$]` will be treated as dynamic optional routes. For example, the following file directory:
|
172
|
+
|
173
|
+
```bash
|
174
|
+
└── routes
|
175
|
+
├── user
|
176
|
+
│ └── [id$]
|
177
|
+
│ └── page.tsx
|
178
|
+
├── blog
|
179
|
+
│ └── page.tsx
|
180
|
+
└── page.tsx
|
181
|
+
```
|
182
|
+
|
183
|
+
The `routes/user/[id$]/page.tsx` file will be converted to the `/user/:id?` route. All routes under `/user` will match this route, and the `id` parameter is optional. This route is usually used to distinguish between **creation** and **editing**.
|
184
|
+
|
185
|
+
In the component, you can use [useParams](/apis/app/runtime/router/router#useparams) to obtain the corresponding named parameter.
|
135
186
|
|
136
|
-
In
|
187
|
+
In the loader, params will be passed as the input parameter of the [loader function](/guides/basic-features/data-fetch#loader-function), and you can get the parameter value through `params.xxx`.
|
137
188
|
|
138
|
-
### Catch
|
189
|
+
### Catch-all Routing
|
139
190
|
|
140
|
-
If a `$.tsx` file
|
191
|
+
If you create a `$.tsx` file under the routes directory, it will be treated as the catch-all routing component. When there is no matching route, this component will be rendered.
|
141
192
|
|
142
193
|
:::note
|
143
|
-
`$.tsx` can be
|
194
|
+
`$.tsx` can be considered as a special `page` route component. When there is a `layout` component in the current directory, `$.tsx` will be rendered as a child component of `layout`.
|
144
195
|
:::
|
145
196
|
|
146
197
|
For example, the following directory structure:
|
147
198
|
|
148
|
-
```
|
199
|
+
```bash
|
149
200
|
└── routes
|
150
201
|
├── $.tsx
|
151
202
|
├── blog
|
@@ -153,7 +204,7 @@ For example, the following directory structure:
|
|
153
204
|
└── page.tsx
|
154
205
|
```
|
155
206
|
|
156
|
-
|
207
|
+
When accessing any path that does not match, the `routes/$.tsx` component will be rendered. Similarly, you can use [useParams](/apis/app/runtime/router/router#useparams) in `$.tsx` to capture the remaining parts of the URL.
|
157
208
|
|
158
209
|
```ts title="$.tsx"
|
159
210
|
import { useParams } from '@modern-js/runtime/router';
|
@@ -162,11 +213,11 @@ const params = useParams();
|
|
162
213
|
params['*']; // => 'aaa/bbb'
|
163
214
|
```
|
164
215
|
|
165
|
-
###
|
216
|
+
### No-path Layout
|
166
217
|
|
167
|
-
When
|
218
|
+
When the directory name starts with `__`, the corresponding directory name will not be converted to an actual route path. For example, the following file directory:
|
168
219
|
|
169
|
-
```
|
220
|
+
```bash
|
170
221
|
.
|
171
222
|
└── routes
|
172
223
|
├── __auth
|
@@ -179,17 +230,17 @@ When a directory name begins with `__`, the corresponding directory name is not
|
|
179
230
|
└── page.tsx
|
180
231
|
```
|
181
232
|
|
182
|
-
Modern.js will generate two routes, `/login` and `/
|
233
|
+
Modern.js will generate two routes, `/login` and `/signup`. The `__auth/layout.tsx` component will serve as the layout component for `login/page.tsx` and `signup/page.tsx`, but `__auth` will not be a route path segment.
|
183
234
|
|
184
|
-
This feature is useful when you need to
|
235
|
+
This feature is very useful when you need to create independent layouts for certain types of routes or want to classify routes.
|
185
236
|
|
186
237
|
### No Layout
|
187
238
|
|
188
|
-
In some cases, the project
|
239
|
+
In some cases, the project requires complex routing, but these routes do not have independent UI layouts. If you create routes like ordinary file directories, it will result in deep directory levels.
|
189
240
|
|
190
|
-
Therefore Modern.js supports
|
241
|
+
Therefore, Modern.js supports using `.` to separate route segments instead of file directories. For example, when you need `/user/profile/2022/edit`, you can directly create the following files:
|
191
242
|
|
192
|
-
```
|
243
|
+
```bash
|
193
244
|
└── routes
|
194
245
|
├── user.profile.[id].edit
|
195
246
|
│ └── page.tsx
|
@@ -197,7 +248,7 @@ Therefore Modern.js supports splitting routing fragments by `.` instead of file
|
|
197
248
|
└── page.tsx
|
198
249
|
```
|
199
250
|
|
200
|
-
When accessing
|
251
|
+
When accessing the route, you will get the following UI layout:
|
201
252
|
|
202
253
|
```tsx
|
203
254
|
<RootLayout>
|
@@ -207,9 +258,9 @@ When accessing a route, you will get the following UI layout:
|
|
207
258
|
|
208
259
|
### (WIP)Loading
|
209
260
|
|
210
|
-
In each
|
261
|
+
In each directory under `routes/`, developers can create a `loading.tsx` file that exports a `<Loading>` component by default.
|
211
262
|
|
212
|
-
When the component
|
263
|
+
When this component and the `layout` component exist in the route directory, the `<Loading>` component will be used as the fallback UI when switching routes in this sub-route. For example, the following file directory:
|
213
264
|
|
214
265
|
```bash
|
215
266
|
.
|
@@ -223,11 +274,50 @@ When the component exists in the routing directory, all routing switches under t
|
|
223
274
|
└── page.tsx
|
224
275
|
```
|
225
276
|
|
226
|
-
When
|
277
|
+
When defining `loading.tsx`, it is equivalent to the following layout:
|
278
|
+
|
279
|
+
When the route is `/`:
|
280
|
+
|
281
|
+
```tsx
|
282
|
+
<Layout>
|
283
|
+
<Suspense fallback={<Loading />}>
|
284
|
+
<Page />
|
285
|
+
</Suspense>
|
286
|
+
</Layout>
|
287
|
+
```
|
288
|
+
|
289
|
+
When the route is `/blog`:
|
290
|
+
|
291
|
+
```tsx
|
292
|
+
<Layout>
|
293
|
+
<Suspense fallback={<Loading />}>
|
294
|
+
<BlogPage />
|
295
|
+
</Suspense>
|
296
|
+
</Layout>
|
297
|
+
```
|
298
|
+
|
299
|
+
When the route is `/blog/123`:
|
300
|
+
|
301
|
+
```tsx
|
302
|
+
<Layout>
|
303
|
+
<Suspense fallback={<Loading />}>
|
304
|
+
<BlogIdPage />
|
305
|
+
</Suspense>
|
306
|
+
</Layout>
|
307
|
+
```
|
308
|
+
|
309
|
+
:::info
|
310
|
+
When the Layout component does not exist in the directory, the Loading component in that directory will not take effect. Modern.js recommends having a root Layout and root Loading.
|
311
|
+
|
312
|
+
:::
|
313
|
+
|
314
|
+
When the route jumps from `/` to `/blog`, if the JS Chunk of the `blog/page` component has not been loaded yet, the UI of the component exported in `loading.tsx` will be displayed first.
|
315
|
+
|
316
|
+
Similarly, when the route jumps from `/` or `/blog` to `/blog/123`, if the JS Chunk of the `blog/[id]/page` component has not been loaded yet, the UI of the component exported in `loading.tsx` will be displayed first.
|
227
317
|
|
228
318
|
### Redirect
|
229
319
|
|
230
|
-
You can
|
320
|
+
You can use a [Data Loader](/guides/basic-features/data-fetch) file to redirect a route. For example, if you have a `routes/user/page.tsx` file and want to redirect the corresponding route, you can create a `routes/user/page.loader.ts` file:
|
231
321
|
|
232
322
|
```ts title="routes/user/page.loader.ts"
|
233
323
|
import { redirect } from '@modern-js/runtime/router';
|
@@ -243,15 +333,13 @@ export default () => {
|
|
243
333
|
|
244
334
|
### ErrorBoundary
|
245
335
|
|
246
|
-
In each
|
247
|
-
|
248
|
-
When the component exists in a routing directory, the component render error is caught by the `ErrorBoundary` component. The `<ErrorBoundary>` component does not take effect when the directory does not have a `layout.tsx` file defined.
|
336
|
+
In each directory under `routes/`, developers can also define an `error.tsx` file that exports an `<ErrorBoundary>` component by default.
|
249
337
|
|
250
|
-
|
338
|
+
When this component exists in the routes directory, any rendering errors will be caught by the `ErrorBoundary` component. When the `layout.tsx` file is not defined in the directory, the `<ErrorBoundary>` component will not take effect.
|
251
339
|
|
252
|
-
|
340
|
+
`<ErrorBoundary>` can return the UI view when an error occurs. When the `<ErrorBoundary>` component is not declared in the current level, the error will bubble up to a higher-level component until it is caught or thrown. At the same time, when a component has an error, it will only affect the route component and its child components that catch the error. The status and view of other components are not affected and can continue to interact.
|
253
341
|
|
254
|
-
|
342
|
+
In the `<ErrorBoundary>` component, you can use [useRouteError](/apis/app/runtime/router/router#userouteerror) to get specific information about the error:
|
255
343
|
|
256
344
|
```tsx
|
257
345
|
import { useRouteError } from '@modern-js/runtime/router';
|
@@ -266,9 +354,34 @@ export const ErrorBoundary = () => {
|
|
266
354
|
};
|
267
355
|
```
|
268
356
|
|
269
|
-
###
|
357
|
+
### Runtime Configuration
|
358
|
+
|
359
|
+
In each root `Layout` component (`routes/layout.ts`), you can dynamically define runtime configuration:
|
360
|
+
|
361
|
+
|
362
|
+
```tsx title="src/routes/layout.tsx"
|
363
|
+
// Define runtime config
|
364
|
+
import type { AppConfig } from '@modern-js/runtime';
|
365
|
+
|
366
|
+
export const config = (): AppConfig => {
|
367
|
+
return {
|
368
|
+
router: {
|
369
|
+
createRoutes() {
|
370
|
+
return [
|
371
|
+
{
|
372
|
+
path: 'modern',
|
373
|
+
element: <div>modern</div>,
|
374
|
+
},
|
375
|
+
];
|
376
|
+
},
|
377
|
+
},
|
378
|
+
};
|
379
|
+
};
|
380
|
+
```
|
381
|
+
|
382
|
+
### Hooks Before Rendering
|
270
383
|
|
271
|
-
In some scenarios
|
384
|
+
In some scenarios, you may need to perform some operations before rendering the application. You can define an `init` hook in `routes/layout.tsx`. The `init` hook will be executed on both the client and server side. A basic example of usage is as follows:
|
272
385
|
|
273
386
|
```ts title="src/routes/layout.tsx"
|
274
387
|
import type { RuntimeContext } from '@modern-js/runtime';
|
@@ -278,11 +391,10 @@ export const init = (context: RuntimeContext) => {
|
|
278
391
|
};
|
279
392
|
```
|
280
393
|
|
281
|
-
|
394
|
+
By using the `init` hook, you can mount some global data, and the `runtimeContext` variable can be accessed in other parts of the application:
|
282
395
|
|
283
396
|
:::note
|
284
|
-
This feature is useful when the application
|
285
|
-
|
397
|
+
This feature is very useful when the application needs pre-rendered data, custom data injection, or framework migration (such as Next.js).
|
286
398
|
:::
|
287
399
|
|
288
400
|
```ts title="src/routes/layout.tsx"
|
@@ -306,7 +418,7 @@ export default () => {
|
|
306
418
|
};
|
307
419
|
```
|
308
420
|
|
309
|
-
When
|
421
|
+
When used with the SSR feature, the data returned by the `init` hook during SSR can be obtained on the client side. Developers can decide whether to re-fetch data on the client side to overwrite the SSR data. For example:
|
310
422
|
|
311
423
|
```tsx title="src/routes/layout.tsx"
|
312
424
|
import { RuntimeContext } from '@modern-js/runtime';
|
@@ -329,51 +441,37 @@ export const init = (context: RuntimeContext) => {
|
|
329
441
|
};
|
330
442
|
```
|
331
443
|
|
332
|
-
###
|
333
|
-
|
334
|
-
In each root `Layout` component (`routes/layout.ts`), the application runtime configuration can be dynamically defined:
|
335
|
-
|
336
|
-
```ts title="src/routes/layout.tsx"
|
337
|
-
import type { AppConfig } from '@modern-js/runtime';
|
444
|
+
### Preloading
|
338
445
|
|
339
|
-
|
340
|
-
return {
|
341
|
-
router: {
|
342
|
-
supportHtml5History: false,
|
343
|
-
},
|
344
|
-
};
|
345
|
-
};
|
346
|
-
```
|
347
|
-
|
348
|
-
### Prefetch
|
446
|
+
In conventional routing, Modern.js automatically splits routes into chunks based on the route. When a user visits a specific route, the corresponding chunk will be loaded automatically, effectively reducing the loading time of the initial screen.
|
349
447
|
|
350
|
-
|
448
|
+
However, this also brings a problem: if the chunk corresponding to the route has not finished loading when the user visits the route, a white screen will appear.
|
351
449
|
|
352
|
-
In this case you can
|
450
|
+
In this case, you can define a `Loading` component to display a custom `Loading` component before the static resources are loaded.
|
353
451
|
|
354
|
-
To further improve the user experience and reduce time
|
452
|
+
To further improve the user experience and reduce loading time, Modern.js supports defining the `prefetch` attribute on the Link component to preload static resources and data. The `prefetch` attribute has three optional values:
|
355
453
|
|
356
|
-
```
|
454
|
+
```tsx
|
357
455
|
<Link prefetch="intent" to="page">
|
358
456
|
```
|
359
457
|
|
360
458
|
:::info
|
361
|
-
- This feature is currently only supported in Webpack projects
|
362
|
-
-
|
459
|
+
- This feature is currently only supported in Webpack projects and not yet supported in Rspack projects.
|
460
|
+
- Preloading data currently only preloads the data returned by the [Data Loader](/guides/basic-features/data-fetch) in SSR projects.
|
363
461
|
|
364
462
|
:::
|
365
463
|
|
366
|
-
- `none
|
367
|
-
- `intent
|
368
|
-
- `render
|
464
|
+
- `none`: default value, no prefetching, no additional behavior.
|
465
|
+
- `intent`: This is the value we recommend for most scenarios. When you hover over the Link, the corresponding chunk and data defined in the data loader will be loaded automatically. When you move the mouse away, the loading will be cancelled automatically. In our tests, even fast clicks can reduce loading time by about 200ms.
|
466
|
+
- `render`: The corresponding chunk and data defined in the Data Loader will be loaded when the Link component is rendered.
|
369
467
|
|
370
468
|
#### FAQ
|
371
469
|
|
372
|
-
1. What is the difference between using `render` and not
|
470
|
+
1. What is the difference between using `render` and not splitting static resources based on the route?
|
373
471
|
|
374
|
-
-
|
375
|
-
-
|
376
|
-
-
|
472
|
+
- By using `render`, you can specify which routes to load during the initial screen, and you can control the rendering so that only when the `Link` component enters the visible area, the `Link` component will be rendered.
|
473
|
+
- By using `render`, static resources will only be loaded when the system is idle, and will not compete with the static resources of the initial screen for network resources.
|
474
|
+
- In the SSR scenario, data will also be pre-fetched.
|
377
475
|
|
378
476
|
import Motivation from '@site-docs-en/components/convention-routing-motivation'
|
379
477
|
|
@@ -383,9 +481,9 @@ import Practice from '@site-docs-en/components/routes-practice'
|
|
383
481
|
|
384
482
|
<Practice/>
|
385
483
|
|
386
|
-
## Self-controlled
|
484
|
+
## Self-controlled Routing
|
387
485
|
|
388
|
-
With `src/App.tsx` as the
|
486
|
+
With `src/App.tsx` as the convention for entry points, Modern.js will not perform any additional routing operations. Developers can use the API of [React Router 6](https://reactrouter.com/en/main) for development, for example:
|
389
487
|
|
390
488
|
```ts title="src/App.tsx"
|
391
489
|
import { BrowserRouter, Route, Routes } from '@modern-js/runtime/router';
|
@@ -403,16 +501,14 @@ export default () => {
|
|
403
501
|
```
|
404
502
|
|
405
503
|
:::note
|
406
|
-
Modern.js
|
504
|
+
Modern.js provides a series of optimizations for resource loading and rendering for conventional routing by default, and provides out-of-the-box SSR capabilities. When using self-controlled routing, developers need to encapsulate these capabilities themselves. It is recommended to use conventional routing.
|
407
505
|
:::
|
408
506
|
|
409
|
-
|
410
|
-
|
411
|
-
```tsx title="src/App.tsx"
|
507
|
+
When using self-controlled routing, if the developer turns off the [`runtime.router`](/configure/app/runtime/router) configuration and uses `react-router-dom` directly, they also need to wrap it according to the React Router documentation.
|
412
508
|
|
413
509
|
## Other
|
414
510
|
|
415
|
-
By default, Modern.js
|
511
|
+
By default, Modern.js will enable the built-in routing scheme, which is React Router.
|
416
512
|
|
417
513
|
```js
|
418
514
|
export default defineConfig({
|
@@ -422,7 +518,7 @@ export default defineConfig({
|
|
422
518
|
});
|
423
519
|
```
|
424
520
|
|
425
|
-
Modern.js exposes the React Router
|
521
|
+
Modern.js exposes the API of React Router from the `@modern-js/runtime/router` namespace for developers to use, ensuring that developers and Modern.js use the same code. In addition, in this case, the React Router code will be bundled into the JS output. If the project already has its own routing scheme or does not need to use client-side routing, this feature can be turned off.
|
426
522
|
|
427
523
|
```js
|
428
524
|
export default defineConfig({
|
@@ -260,9 +260,9 @@ export default (): CliPlugin => ({
|
|
260
260
|
### `afterDev`
|
261
261
|
|
262
262
|
- Function: Tasks to be executed after the main process of `dev` command
|
263
|
-
- Execution Stage:
|
263
|
+
- Execution Stage: It is executed after each compilation is completed when running the `dev` command
|
264
264
|
- Hook Model: AsyncWorkflow
|
265
|
-
- Type: `AsyncWorkflow<
|
265
|
+
- Type: `AsyncWorkflow<{ isFirstCompile: boolean }, unknown>`
|
266
266
|
- Usage Example:
|
267
267
|
|
268
268
|
```ts
|
@@ -279,6 +279,24 @@ export default (): CliPlugin => ({
|
|
279
279
|
});
|
280
280
|
```
|
281
281
|
|
282
|
+
`afterDev` will be executed after each compilation is completed, you can use the `isFirstCompile` param to determine whether it is the first compilation:
|
283
|
+
|
284
|
+
```ts
|
285
|
+
import type { CliPlugin } from '@modern-js/core';
|
286
|
+
|
287
|
+
export default (): CliPlugin => ({
|
288
|
+
setup(api) {
|
289
|
+
return {
|
290
|
+
afterDev: ({ isFirstCompile }) => {
|
291
|
+
if (isFirstCompile) {
|
292
|
+
// do something
|
293
|
+
}
|
294
|
+
},
|
295
|
+
};
|
296
|
+
},
|
297
|
+
});
|
298
|
+
```
|
299
|
+
|
282
300
|
### `beforeCreateCompiler`
|
283
301
|
|
284
302
|
- Function: Provides access to the Webpack configuration used to create the Webpack Compiler within middleware functions.
|
@@ -438,7 +456,7 @@ import type { CliPlugin } from '@modern-js/core';
|
|
438
456
|
export default (): CliPlugin => ({
|
439
457
|
setup(api) {
|
440
458
|
return {
|
441
|
-
|
459
|
+
modifyEntryExport({ entrypoint, exportStatement }) {
|
442
460
|
return {
|
443
461
|
entrypoint,
|
444
462
|
exportStatement: [`export const foo = 'test'`, exportStatement].join(
|
@@ -776,7 +794,7 @@ export default (): Plugin => ({
|
|
776
794
|
);
|
777
795
|
};
|
778
796
|
return next({
|
779
|
-
App: hoistNonReactStatics(AppWrapper, App)
|
797
|
+
App: hoistNonReactStatics(AppWrapper, App),
|
780
798
|
});
|
781
799
|
},
|
782
800
|
};
|
@@ -106,6 +106,28 @@ function App() {
|
|
106
106
|
}
|
107
107
|
```
|
108
108
|
|
109
|
+
### useRouteError
|
110
|
+
|
111
|
+
```ts
|
112
|
+
export declare function useRouteError(): unknown;
|
113
|
+
```
|
114
|
+
|
115
|
+
`useRouteError` 返回离 ErrorBoundary 定义最近的路由渲染错误信息。
|
116
|
+
|
117
|
+
```tsx
|
118
|
+
import { useRouteError } from '@modern-js/runtime/router';
|
119
|
+
const ErrorBoundary = () => {
|
120
|
+
const error = useRouteError();
|
121
|
+
return (
|
122
|
+
<div>
|
123
|
+
<h1>{error.status}</h1>
|
124
|
+
<h2>{error.message}</h2>
|
125
|
+
</div>
|
126
|
+
);
|
127
|
+
};
|
128
|
+
export default ErrorBoundary;
|
129
|
+
```
|
130
|
+
|
109
131
|
## 组件
|
110
132
|
|
111
133
|
### Link
|
@@ -0,0 +1,13 @@
|
|
1
|
+
---
|
2
|
+
sidebar_label: nonce
|
3
|
+
---
|
4
|
+
|
5
|
+
# security.nonce
|
6
|
+
|
7
|
+
:::tip
|
8
|
+
该配置由 Modern.js Builder 提供,更多信息可参考 [security.nonce](https://modernjs.dev/builder/api/config-security.html#securitynonce)。
|
9
|
+
:::
|
10
|
+
|
11
|
+
import Main from '@modern-js/builder-doc/docs/zh/config/security/nonce.md';
|
12
|
+
|
13
|
+
<Main />
|