@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
@@ -4,17 +4,20 @@ sidebar_position: 2
4
4
 
5
5
  # Routing
6
6
 
7
- 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**.
7
+ Modern.js routing is based on [React Router 6](https://reactrouter.com/en/main), offering file convention-based routing capabilities and supporting the industry-popular **nested routing** pattern. When an entry is recognized as [conventional routing](/guides/concept/entries.html#conventional-routing), Modern.js automatically generates the corresponding routing structure based on the file system.
8
8
 
9
9
  :::note
10
- The routing mentioned in this section refers to client-side routing, i.e., SPA routing.
10
+ The routing mentioned in this section all refers to conventional routing.
11
11
  :::
12
12
 
13
- ## Conventional Routing
13
+ ## What is Nested Routing
14
14
 
15
- With `routes/` as the convention for entry points, Modern.js automatically generates the corresponding routing structure based on the file system.
15
+ Nested routing is a pattern that couples URL segments with the component hierarchy and data. Typically, URL segments determine:
16
16
 
17
- 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.
17
+ - The layouts to render on the page
18
+ - The data dependencies of those layouts
19
+
20
+ Therefore, when using nested routing, the page's routing and UI structure are in correspondence. We will introduce this routing pattern in detail.
18
21
 
19
22
  ```bash
20
23
  /user/johnny/profile /user/johnny/posts
@@ -27,62 +30,45 @@ Modern.js supports the popular conventional routing mode in the industry: **Nest
27
30
  +------------------+ +-----------------+
28
31
  ```
29
32
 
30
- ### Routing File Convention
33
+ ## Routing File Conventions
31
34
 
32
- 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
+ In the `routes/` directory, subdirectory names are mapped to route URLs. Modern.js has two file conventions: `layout.tsx` and `page.tsx`. These files determine the layout hierarchy of the application:
33
36
 
34
- For example, the following directory structure:
37
+ - `page.tsx`: This is the content component. When this file exists in a directory, the corresponding route URL is accessible.
38
+ - `layout.tsx`: This is the layout component and controls the layout of all sub-routes in its directory by using `<Outlet>` to represent child components.
35
39
 
36
- ```bash
37
- .
38
- └── routes
39
- ├── page.tsx
40
- └── user
41
- └── page.tsx
42
- ```
40
+ :::tip
41
+ `.ts`, `.js`, `.jsx`, or `.tsx` file extensions can be used for the above convention files.
42
+ :::
43
43
 
44
- This will generate the following two routes:
44
+ ### Page
45
45
 
46
- - `/`
47
- - `/user`
46
+ The `<Page>` component refers to all `page.tsx` files in the `routes/` directory and is the leaf component for all routes. All routes should end with a `<Page>` component except for wildcard routes.
48
47
 
49
- When `layout.tsx` is added, assuming the following directory:
48
+ ```tsx title=routes/page.tsx
49
+ export default () => {
50
+ return <div>Hello world</div>
51
+ };
52
+ ```
50
53
 
51
- :::info
52
- 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.
53
- :::
54
+ When the application has the following directory structure:
54
55
 
55
56
  ```bash
56
57
  .
57
58
  └── routes
58
- ├── layout.tsx
59
59
  ├── page.tsx
60
60
  └── user
61
- ├── layout.tsx
62
61
  └── page.tsx
63
62
  ```
64
63
 
65
- When the route is `/`, the following UI layout will be displayed:
66
-
67
- ```tsx
68
- <Layout>
69
- <Page />
70
- </Layout>
71
- ```
72
-
73
- 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:
64
+ The following two routes will be produced:
74
65
 
75
- ```tsx
76
- <Layout>
77
- <UserLayout>
78
- <UserPage />
79
- </UserLayout>
80
- </Layout>
81
- ```
66
+ - `/`
67
+ - `/user`
82
68
 
83
- #### Layout
69
+ ### Layout
84
70
 
85
- 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.
71
+ The `<Layout>` component refers to all `layout.tsx` files in the `routes/` directory. These represent the layout of their respective route segments, using `<Outlet>` for child components.
86
72
 
87
73
  ```tsx title=routes/layout.tsx
88
74
  import { Link, Outlet, useLoaderData } from '@modern-js/runtime/router';
@@ -97,11 +83,10 @@ export default () => {
97
83
  ```
98
84
 
99
85
  :::note
100
- `<Outlet>` is a new API in React Router 6. For more details, please refer to [Outlet](https://reactrouter.com/en/main/components/outlet#outlet).
101
-
86
+ `<Outlet>` is an API provided by React Router 6. For more details, see [Outlet](https://reactrouter.com/en/main/components/outlet#outlet).
102
87
  :::
103
88
 
104
- To simplify the introduction of the relationship between `<Layout>` and `<Outlet>`, the following file directory is used as an example:
89
+ Under different directory structures, the components represented by `<Outlet>` are also different. To illustrate the relationship between `<Layout>` and `<Outlet>`, let's consider the following directory structure:
105
90
 
106
91
  ```bash
107
92
  .
@@ -115,7 +100,7 @@ To simplify the introduction of the relationship between `<Layout>` and `<Outlet
115
100
  └── page.tsx
116
101
  ```
117
102
 
118
- 1. When the route is `/`, the `<Outlet>` in `routes/layout.tsx` represents the component exported in `routes/page.tsx`, generating the following UI structure:
103
+ 1. When the route is `/`, the `<Outlet>` in `routes/layout.tsx` represents the component exported from `routes/page.tsx`. The UI structure of the route is:
119
104
 
120
105
  ```tsx
121
106
  <Layout>
@@ -123,7 +108,7 @@ To simplify the introduction of the relationship between `<Layout>` and `<Outlet
123
108
  </Layout>
124
109
  ```
125
110
 
126
- 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:
111
+ 2. When the route is `/blog`, the `<Outlet>` in `routes/layout.tsx` represents the component exported from `routes/blog/page.tsx`. The UI structure of the route is:
127
112
 
128
113
  ```tsx
129
114
  <Layout>
@@ -131,7 +116,7 @@ To simplify the introduction of the relationship between `<Layout>` and `<Outlet
131
116
  </Layout>
132
117
  ```
133
118
 
134
- 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:
119
+ 3. When the route is `/user`, the `<Outlet>` in `routes/layout.tsx` represents the component exported from `routes/user/layout.tsx`. The `<Outlet>` in `routes/user/layout.tsx` represents the component exported from `routes/user/page.tsx`. The UI structure of the route is:
135
120
 
136
121
  ```tsx
137
122
  <Layout>
@@ -141,92 +126,89 @@ To simplify the introduction of the relationship between `<Layout>` and `<Outlet
141
126
  </Layout>
142
127
  ```
143
128
 
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.
145
-
146
- #### Page
147
-
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.
149
-
150
- #### Config
151
-
152
- Each `Layout`,`$` or `Page` file can define its own `config` file, such as `page.config.ts`. In this file, we have an conventinal on a named export called `handle`, which you can define any properties:
153
-
154
- ```ts title="routes/blog/page.config.ts"
155
- export const handle = {
156
- breadcrumbName: 'profile',
157
- };
158
- ```
159
-
160
- These properties as defined are available via the [`useMatches`](https://reactrouter.com/en/main/hooks/use-matches) hook:
161
-
162
- ```ts title="routes/layout.ts"
163
- export default () => {
164
- const matches = useMatches();
165
- const breadcrumbs = matches.map(
166
- matchedRoute => matchedRoute?.handle?.breadcrumbName,
167
- );
168
- return <Breadcrumb names={breadcrumbs}></Breadcrumb>;
169
- };
170
- ```
129
+ In summary, if there is a `layout.tsx` in the sub-route's directory, the `<Outlet>` in the parent `layout.tsx` corresponds to the `layout.tsx` in the sub-route's directory. Otherwise, it corresponds to the `page.tsx` in the sub-route's directory.
171
130
 
172
- ### Dynamic Routing
131
+ ## Dynamic Routes
173
132
 
174
- Routes generated from file directories named with `[]` will be handled as dynamic routes. For example, the following file directory:
133
+ Files and directories named with `[]` are turned into dynamic routes. For instance, consider the following directory structure:
175
134
 
176
135
  ```bash
136
+ .
177
137
  └── routes
178
- ├── [id]
179
- │ └── page.tsx
180
138
  ├── blog
181
- │ └── page.tsx
139
+ │ └── [id]
140
+ │ └── page.tsx
182
141
  └── page.tsx
183
142
  ```
184
143
 
185
- 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.
144
+ The `routes/[id]/page.tsx` file will be converted to the `/:id` route. Apart from the `/blog` route that can be exactly matched, all `/xxx` paths will match this route.
186
145
 
187
- In the component, you can use [useParams](/apis/app/runtime/router/router#useparams) to get the corresponding named parameter.
146
+ In the component, you can use [useParams](/apis/app/runtime/router/router#useparams) to get parameters named accordingly.
147
+
148
+ ```tsx
149
+ import { useParams } from '@modern-js/runtime/router';
188
150
 
189
- In the loader, params will be passed as the input parameter of the [loader function](/guides/basic-features/data/data-fetch#loader-function), and you can get the parameter value through `params.xxx`.
151
+ function Blog() {
152
+ const { id } = useParams();
153
+ return <div>current blog ID is: {id}</div>;
154
+ }
155
+ export default Blog;
156
+ ```
190
157
 
191
- ### Dynamic Optional Routing
158
+ ## Optional Dynamic Routes
192
159
 
193
- Routes generated from file directories named with `[$]` will be treated as dynamic optional routes. For example, the following file directory:
160
+ Files and directories named with `[$]` are turned into optional dynamic routes. For example, the following directory structure:
194
161
 
195
162
  ```bash
163
+ .
196
164
  └── routes
197
- ├── user
165
+ ├── blog
198
166
  │ └── [id$]
199
167
  │ └── page.tsx
200
- ├── blog
201
- │ └── page.tsx
202
168
  └── page.tsx
203
169
  ```
204
170
 
205
- 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**.
171
+ 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 can be used to distinguish between **create** and **edit** actions.
172
+
173
+ ```tsx
174
+ import { useParams } from '@modern-js/runtime/router';
206
175
 
207
- In the component, you can use [useParams](/apis/app/runtime/router/router#useparams) to get the corresponding named parameter.
176
+ function Blog() {
177
+ const { id } = useParams();
178
+ if (id) {
179
+ return <div>current blog ID is: {id}</div>;
180
+ }
208
181
 
209
- In the loader, params will be passed as the input parameter of the [loader function](/guides/basic-features/data/data-fetch#loader-function), and you can get the parameter value through `params.xxx`.
182
+ return <div>create new blog</div>;
183
+ }
184
+ export default Blog;
185
+ ```
210
186
 
211
- ### Catch-all Routing
187
+ ## Wildcard Routes
212
188
 
213
- 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.
189
+ If there is a `$.tsx` file in a subdirectory, it acts as a wildcard route component and will be rendered when no other routes match.
214
190
 
215
191
  :::note
216
- `$.tsx` can be considered as a special `page` route component. When there is a `layout.tsx` file in the current directory, `$.tsx` will be rendered as a child component of `layout`.
192
+ `$.tsx` can be thought of as a special `<Page>` component. If no routes match, `$.tsx` will be rendered as a child component of the `<Layout>`.
193
+ :::
194
+
195
+ :::warning
196
+ If there is no `<Layout>` component in the current directory, `$.tsx` will not have any effect.
217
197
  :::
218
198
 
219
- For example, the following directory structure:
199
+ For example, consider the following directory structure:
220
200
 
221
201
  ```bash
202
+ .
222
203
  └── routes
223
- ├── $.tsx
224
204
  ├── blog
225
- └── page.tsx
205
+ ├── $.tsx
206
+ │ └── layout.tsx
207
+ ├── layout.tsx
226
208
  └── page.tsx
227
209
  ```
228
210
 
229
- When accessing any path that does not match(For example `/blog/a`), the `routes/blog/$.tsx` component will be rendered, because there is `layout.tsx` here, the rendered UI is as follows.
211
+ When you visit `/blog/a` and no routes match, the page will render the `routes/blog/$.tsx` component. The UI structure of the route is:
230
212
 
231
213
  ```tsx
232
214
  <RootLayout>
@@ -236,20 +218,76 @@ When accessing any path that does not match(For example `/blog/a`), the `routes/
236
218
  </RootLayout>
237
219
  ```
238
220
 
239
- If you want access to `/blog` to also match the `blog/$.tsx` file, you need to delete the `blog/layout.tsx` file in the same directory and make sure that there are no other subroutes under `blog`.
221
+ If you want `/blog` to match the `blog/$.tsx` file as well, you need to remove the `blog.tsx` file from the same directory and ensure there are no other sub-routes under `blog`.
240
222
 
241
- As same, you can use [useParams](/apis/app/runtime/router/router#useparams) in `$.tsx` to capture the remaining parts of the URL.
223
+ Similarly, you can use [useParams](/apis/app/runtime/router/router#useparams) to capture the remaining part of the URL in the `$.tsx` component.
242
224
 
243
225
  ```ts title="$.tsx"
244
226
  import { useParams } from '@modern-js/runtime/router';
245
- // When the path is `/aaa/bbb`
246
- const params = useParams();
247
- params['*']; // => 'aaa/bbb'
227
+
228
+ function Blog() {
229
+ // When the path is `/blog/aaa/bbb`
230
+ const params = useParams();
231
+ console.log(params) // ---> { '*': 'aaa/bbb' }
232
+
233
+ return <div>current blog URL is {params["*"]}</div>;
234
+ }
235
+ export default Blog;
248
236
  ```
249
237
 
250
- ### No-path Layout
238
+ ### Custom 404 Page
251
239
 
252
- When the directory name starts with `__`, the directory name will not be converted to an actual route path. For example, the following file directory:
240
+ Wildcard routes can be added to any subdirectory in the `routes/` directory. A common use case is to customize a 404 page at any level using a `$.tsx` file.
241
+
242
+ For instance, if you want to show a 404 page for all unmatched routes, you can add a `routes/$.tsx` file:
243
+
244
+ ```bash
245
+ .
246
+ └── routes
247
+ ├── $.tsx
248
+ ├── blog
249
+ │ └── [id$]
250
+ │ └── page.tsx
251
+ ├── layout.tsx
252
+ └── page.tsx
253
+ ```
254
+
255
+ ```tsx
256
+ function Page404() {
257
+ return <div>404 Not Found</div>;
258
+ }
259
+ export default Page404;
260
+ ```
261
+
262
+ At this point, when accessing routes other than `/` or `/blog/*`, they will match the `routes/$.tsx` component and display a 404 page.
263
+
264
+ ## Route Handle Configuration
265
+
266
+ In some scenarios, each route might have its own data which the application needs to access in other components. A common example is retrieving breadcrumb information for the matched route.
267
+
268
+ Modern.js provides a convention where each `Layout`, `$`, or `Page` file can define its own `config` file such as `page.config.ts`. In this file, we conventionally export a named export `handle`, in which you can define any properties:
269
+
270
+ ```ts title="routes/page.config.ts"
271
+ export const handle = {
272
+ breadcrumbName: 'profile',
273
+ };
274
+ ```
275
+
276
+ These defined properties can be accessed using the [`useMatches`](https://reactrouter.com/en/main/hooks/use-matches) hook.
277
+
278
+ ```ts title="routes/layout.ts"
279
+ export default () => {
280
+ const matches = useMatches();
281
+ const breadcrumbs = matches.map(
282
+ matchedRoute => matchedRoute?.handle?.breadcrumbName,
283
+ );
284
+ return <Breadcrumb names={breadcrumbs}></Breadcrumb>;
285
+ };
286
+ ```
287
+
288
+ ## Pathless Layouts
289
+
290
+ When a directory name starts with `__`, the corresponding directory name will not be converted into an actual route path, for example:
253
291
 
254
292
  ```bash
255
293
  .
@@ -258,21 +296,21 @@ When the directory name starts with `__`, the directory name will not be convert
258
296
  │ ├── layout.tsx
259
297
  │ ├── login
260
298
  │ │ └── page.tsx
261
- │ └── signup
299
+ │ └── sign
262
300
  │ └── page.tsx
263
301
  ├── layout.tsx
264
302
  └── page.tsx
265
303
  ```
266
304
 
267
- 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.
305
+ Modern.js will generate `/login` and `/sign` routes, and the `__auth/layout.tsx` component will serve as the layout for `login/page.tsx` and `sign/page.tsx`, but `__auth` will not appear as a path segment in the URL.
268
306
 
269
- This feature is very useful when you need to create independent layouts for certain types of routes or want to classify routes.
307
+ This feature is useful when you need to create independent layouts or categorize routes without adding additional path segments.
270
308
 
271
- ### No Layout
309
+ ## Pathless File Segments
272
310
 
273
- 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.
311
+ In some cases, a project may need complex routes that do not have independent UI layouts. Creating these routes as regular directories can lead to deeply nested directories.
274
312
 
275
- 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:
313
+ Modern.js supports replacing directory names with `.` to divide route segments. For example, to create a route like `/user/profile/2022/edit`, you can create the following file:
276
314
 
277
315
  ```bash
278
316
  └── routes
@@ -282,19 +320,97 @@ Therefore, Modern.js supports using `.` to separate route segments instead of fi
282
320
  └── page.tsx
283
321
  ```
284
322
 
285
- When accessing the route, you will get the following UI layout:
323
+ When accessed, the resulting route will have the following UI structure:
286
324
 
287
325
  ```tsx
288
326
  <RootLayout>
289
- <UserProfileEdit /> // routes/user.profile.[id].edit/page.tsx
327
+ {/* routes/user.profile.[id].edit/page.tsx */}
328
+ <UserProfileEdit />
290
329
  </RootLayout>
291
330
  ```
292
331
 
293
- ### Loading (Experimental)
332
+ ## Route Redirections
333
+
334
+ In some applications, you may need to redirect to another route based on user identity or other data conditions. In Modern.js, you can use a [`Data Loader`](/guides/basic-features/data/data-fetch) file to fetch data or use traditional React components with `useEffect`.
294
335
 
295
- In each directory under `routes/`, developers can create a `loading.tsx` file that exports a `<Loading>` component by default.
336
+ ### Redirecting in Data Loader
296
337
 
297
- 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:
338
+ Create a `page.data.ts` file in the same directory as `page.tsx`. This file is the Data Loader for that route. In the Data Loader, you can call the `redirect` API to perform route redirections.
339
+
340
+ ```ts title="routes/user/page.data.ts"
341
+ import { redirect } from '@modern-js/runtime/router';
342
+
343
+ export const loader = () => {
344
+ const user = await getUser();
345
+ if (!user) {
346
+ return redirect('/login');
347
+ }
348
+ return null;
349
+ };
350
+ ```
351
+
352
+ ### Redirecting in a Component
353
+
354
+ To perform a redirection within a component, use the `useNavigate` hook as shown below:
355
+
356
+ ```ts title="routes/user/page.ts"
357
+ import { useNavigate } from '@modern-js/runtime/router';
358
+ import { useEffect } from 'react';
359
+
360
+ export default () => {
361
+ const navigate = useNavigate();
362
+ useEffect(() => {
363
+ getUser().then(user => {
364
+ if (!user) {
365
+ navigate('/login');
366
+ }
367
+ });
368
+ });
369
+
370
+ return <div>Hello World</div>;
371
+ };
372
+ ```
373
+
374
+ ## Error Handling
375
+
376
+ In each directory under `routes/`, developers can define an `error.tsx` file that exports an `<ErrorBoundary>` component. When this component is present, rendering errors in the route directory will be caught by the `ErrorBoundary` component.
377
+
378
+ `<ErrorBoundary>` can return the UI view when an error occurs. If the current level does not declare an `<ErrorBoundary>` component, errors will bubble up to higher-level components until they are caught or thrown. Additionally, when an error occurs within a component, it only affects the route component and its children, leaving the state and view of other components unaffected and interactive.
379
+
380
+ {/* Todo API Routes */}
381
+
382
+ In the `<ErrorBoundary>` component, you can use [useRouteError](/apis/app/runtime/router/router#userouteerror) to obtain specific error information:
383
+
384
+ ```tsx
385
+ import { useRouteError } from '@modern-js/runtime/router';
386
+
387
+ const ErrorBoundary = () => {
388
+ const error = useRouteError();
389
+ return (
390
+ <div>
391
+ <h1>{error.status}</h1>
392
+ <h2>{error.message}</h2>
393
+ </div>
394
+ );
395
+ };
396
+ export default ErrorBoundary;
397
+ ```
398
+
399
+ ## Loading (Experimental)
400
+
401
+ :::info Experimental
402
+ This feature is currently experimental, and its API may change in the future.
403
+ :::
404
+
405
+ In conventional routing, Modern.js automatically splits routes into chunks (each route loads as a separate JS chunk). When users visit a specific route, the corresponding chunk is automatically loaded, effectively reducing the first-screen load time. However, this can lead to a white screen if the route's chunk is not yet loaded.
406
+
407
+ Modern.js supports solving this issue with a `loading.tsx` file. Each directory under `routes/` can create a `loading.tsx` file that exports a `<Loading>` component.
408
+
409
+ :::warning
410
+ If there is no `<Layout>` component in the current directory, `loading.tsx` will not have any effect. To ensure a good user experience, Modern.js recommends adding a root Loading component to each application.
411
+ :::
412
+
413
+ When both this component and a `layout` component exist in the route directory, all child routes under this level will first display the UI from the exported `<Loading>` component until the corresponding JS chunk is fully loaded. For example, with the following file structure:
298
414
 
299
415
  ```bash
300
416
  .
@@ -308,11 +424,9 @@ When this component and the `layout` component exist in the route directory, the
308
424
  └── page.tsx
309
425
  ```
310
426
 
311
- When defining `loading.tsx`, it is equivalent to the following layout:
427
+ When defining a `loading.tsx`, if the route transitions from `/` to `/blog` or from `/blog` to `/blog/123`, and the JS chunk for the route is not yet loaded, the UI from the `<Loading>` component will be displayed first. This results in the following UI structure:
312
428
 
313
- When the route is `/`:
314
-
315
- ```tsx
429
+ ```tsx title=When the route is "/"
316
430
  <Layout>
317
431
  <Suspense fallback={<Loading />}>
318
432
  <Page />
@@ -320,9 +434,7 @@ When the route is `/`:
320
434
  </Layout>
321
435
  ```
322
436
 
323
- When the route is `/blog`:
324
-
325
- ```tsx
437
+ ```tsx title=When the route is "/blog"
326
438
  <Layout>
327
439
  <Suspense fallback={<Loading />}>
328
440
  <BlogPage />
@@ -330,9 +442,7 @@ When the route is `/blog`:
330
442
  </Layout>
331
443
  ```
332
444
 
333
- When the route is `/blog/123`:
334
-
335
- ```tsx
445
+ ```tsx title=When the route is "/blog/123"
336
446
  <Layout>
337
447
  <Suspense fallback={<Loading />}>
338
448
  <BlogIdPage />
@@ -340,71 +450,45 @@ When the route is `/blog/123`:
340
450
  </Layout>
341
451
  ```
342
452
 
343
- :::info
344
- 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.
345
-
346
- :::
347
-
348
- 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.
453
+ ## Prefetching
349
454
 
350
- 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.
455
+ Most white screens during route transitions can be optimized by defining a `<Loading>` component. Modern.js also supports preloading static resources and data with the `prefetch` attribute on `<Link>` components.
351
456
 
352
- ### Redirect
457
+ For applications with higher performance requirements, prefetching can further enhance the user experience by reducing the time spent displaying the `<Loading>` component:
353
458
 
354
- You can use a [Data Loader](/guides/basic-features/data/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.data.ts` file:
355
-
356
- ```ts title="routes/user/page.data.ts"
357
- import { redirect } from '@modern-js/runtime/router';
358
-
359
- export const loader = () => {
360
- const user = await getUser();
361
- if (!user) {
362
- return redirect('/login');
363
- }
364
- return null;
365
- };
459
+ ```tsx
460
+ <Link prefetch="intent" to="page">
366
461
  ```
367
462
 
368
- If you want to redirect in a component,you can navigate by `useNavigate` hook, for example:
463
+ :::tip
369
464
 
370
- ```ts title="routes/user/page.ts"
371
- import { useNavigate } from '@modern-js/runtime/router';
465
+ - This feature is currently only supported in Webpack projects and not in Rspack projects.
466
+ - Data preloading currently only preloads data returned by the [Data Loader](/guides/basic-features/data/data-fetch) in SSR projects.
372
467
 
373
- export default () => {
374
- const navigate = useNavigate();
375
- navigate('/login');
376
- };
377
- ```
468
+ :::
378
469
 
379
- ### ErrorBoundary
470
+ The `prefetch` attribute has three optional values:
380
471
 
381
- In each directory under `routes/`, developers can also define an `error.tsx` file that exports an `<ErrorBoundary>` component by default.
472
+ - `none`: The default value. No prefetching, no additional behavior.
473
+ - `intent`: This is the recommended value for most scenarios. When you hover over the Link, it will automatically start loading the corresponding chunk and the data defined in the Data Loader. If the mouse moves away, the loading is automatically canceled. In our tests, even quick clicks can reduce load time by approximately 200ms.
474
+ - `render`: When the `<Link>` component is rendered, it begins loading the corresponding chunk and data defined in the Data Loader.
382
475
 
383
- 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.
476
+ :::details Difference Between "render" and Not Using Route Splitting
477
+ - `render` allows you to control the timing of route splitting, triggering only when the `<Link>` component enters the viewport. You can control the loading timing of the split by adjusting the rendering position of the `<Link>` component.
478
+ - `render` loads static resources only during idle times, thus not occupying the loading time of critical modules.
479
+ - Besides preloading route splits, `render` will also initiate data prefetching in SSR projects.
384
480
 
385
- `<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.
481
+ :::
386
482
 
387
- In the `<ErrorBoundary>` component, you can use [useRouteError](/apis/app/runtime/router/router#userouteerror) to get specific information about the error:
388
483
 
389
- ```tsx
390
- import { useRouteError } from '@modern-js/runtime/router';
391
- export const ErrorBoundary = () => {
392
- const error = useRouteError();
393
- return (
394
- <div>
395
- <h1>{error.status}</h1>
396
- <h2>{error.message}</h2>
397
- </div>
398
- );
399
- };
400
- ```
484
+ ## Runtime Configuration
401
485
 
402
- ### Runtime Configuration
486
+ {/* Todo Move to runtime configuration chapter */}
403
487
 
404
- In each root `Layout` component (`routes/layout.ts`), you can dynamically define runtime configuration:
488
+ In the root `<Layout>` component (`routes/layout.ts`), you can dynamically define runtime configuration:
405
489
 
406
490
  ```tsx title="src/routes/layout.tsx"
407
- // Define runtime config
491
+ // Define runtime configuration
408
492
  import type { AppConfig } from '@modern-js/runtime';
409
493
 
410
494
  export const config = (): AppConfig => {
@@ -423,9 +507,11 @@ export const config = (): AppConfig => {
423
507
  };
424
508
  ```
425
509
 
426
- ### Hooks Before Rendering
510
+ ## Pre-render Hooks
511
+
512
+ {/* Todo Move to runtime configuration chapter */}
427
513
 
428
- 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:
514
+ In some scenarios, you need to perform certain actions before the application renders. You can define the `init` hook in `routes/layout.tsx`, which will be executed both on the client and server. A basic example is shown below:
429
515
 
430
516
  ```ts title="src/routes/layout.tsx"
431
517
  import type { RuntimeContext } from '@modern-js/runtime';
@@ -435,10 +521,10 @@ export const init = (context: RuntimeContext) => {
435
521
  };
436
522
  ```
437
523
 
438
- By using the `init` hook, you can mount some global data, and the `runtimeContext` variable can be accessed in other parts of the application:
524
+ With the `init` hook, you can mount some global data that can be accessed elsewhere in the application via the `runtimeContext` variable:
439
525
 
440
526
  :::note
441
- This feature is very useful when the application needs pre-rendered data, custom data injection, or framework migration (such as Next.js).
527
+ This feature is very useful when applications require pre-rendered data, custom data injection, or framework migration (e.g., Next.js).
442
528
  :::
443
529
 
444
530
  ```ts title="src/routes/layout.tsx"
@@ -452,7 +538,7 @@ export const init = (context: RuntimeContext) => {
452
538
  ```
453
539
 
454
540
  ```tsx title="src/routes/page.tsx"
455
- import { useRuntimeContext } from '@modern-js/runtime';
541
+ import { useRuntimeContext } from '@modern-js/runtime;
456
542
 
457
543
  export default () => {
458
544
  const context = useRuntimeContext();
@@ -462,10 +548,10 @@ export default () => {
462
548
  };
463
549
  ```
464
550
 
465
- 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:
551
+ With SSR, the browser can obtain the data returned by `init` during SSR. Developers can decide whether to re-fetch the data on the browser side to override the SSR data. For example:
466
552
 
467
553
  ```tsx title="src/routes/layout.tsx"
468
- import { RuntimeContext } from '@modern-js/runtime';
554
+ import { RuntimeContext } from '@modern-js/runtime;
469
555
 
470
556
  export const init = (context: RuntimeContext) => {
471
557
  if (process.env.MODERN_TARGET === 'node') {
@@ -475,7 +561,7 @@ export const init = (context: RuntimeContext) => {
475
561
  } else {
476
562
  const { context } = runtimeContext;
477
563
  const data = context.getInitData();
478
- // If do not get the expected data
564
+ // If the expected data is not obtained
479
565
  if (!data.message) {
480
566
  return {
481
567
  message: 'Hello World By Client',
@@ -485,94 +571,20 @@ export const init = (context: RuntimeContext) => {
485
571
  };
486
572
  ```
487
573
 
488
- ### Preloading
489
-
490
- 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.
491
-
492
- 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.
493
-
494
- In this case, you can define a `Loading` component to display a custom `Loading` component before the static assets are loaded.
495
-
496
- To further improve the user experience and reduce loading time, Modern.js supports defining the `prefetch` attribute on the Link component to preload static assets and data.
497
-
498
- ```tsx
499
- <Link prefetch="intent" to="page">
500
- ```
501
-
502
- :::info
503
-
504
- - This feature is currently only supported in Webpack projects and not yet supported in Rspack projects.
505
- - Preloading data currently only preloads the data returned by the [Data Loader](/guides/basic-features/data/data-fetch) in SSR projects.
506
-
507
- :::
508
-
509
- The `prefetch` attribute has three optional values:
510
-
511
- - `none`: default value, no prefetching, no additional behavior.
512
- - `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.
513
- - `render`: The corresponding chunk and data defined in the Data Loader will be loaded when the Link component is rendered.
514
-
515
- #### FAQ
516
-
517
- 1. What is the difference between using `render` and not splitting static assets based on the route?
518
-
519
- - 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.
520
- - By using `render`, static assets will only be loaded when the system is idle, and will not compete with the static assets of the initial screen for network assets.
521
- - In the SSR scenario, data will also be pre-fetched.
522
-
523
- import Motivation from '@site-docs-en/components/convention-routing-motivation';
524
-
525
574
  <Motivation />
526
575
 
527
- import Practice from '@site-docs-en/components/routes-practice';
528
-
529
- <Practice />
576
+ ## FAQ
530
577
 
531
- ## Self-controlled Routing
578
+ 1. Why there is `@modern-js/runtime/router` to re-export React Router API
532
579
 
533
- 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:
580
+ Notice that all the code examples in the documentation use API exported from the `@modern-js/runtime/router` package instead of directly using the API exported from the React Router package. So, what is the difference?
534
581
 
535
- ```ts title="src/App.tsx"
536
- import { BrowserRouter, Route, Routes } from '@modern-js/runtime/router';
582
+ The API exported from `@modern-js/runtime/router` is entirely consistent with the API from the React Router package. If you encounter issues while using an API, check the React Router documentation and issues first.
537
583
 
538
- export default () => {
539
- return (
540
- <BrowserRouter>
541
- <Routes>
542
- <Route index element={<div>index</div>} />
543
- <Route path="about" element={<div>about</div>} />
544
- </Routes>
545
- </BrowserRouter>
546
- );
547
- };
548
- ```
584
+ Additionally, when using conventional routing, make sure to use the API from `@modern-js/runtime/router` instead of directly using the React Router API. Modern.js internally installs React Router, and using the React Router API directly in your application may result in two versions of React Router being present, causing unexpected behavior.
549
585
 
550
586
  :::note
551
- 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.
587
+ If you must directly use the React Router package's API (e.g., route behavior wrapped in a unified npm package), you can set [`source.alias`](/configure/app/source/alias) to point `react-router` and `react-router-dom` to the project's dependencies, avoiding the issue of two versions of React Router.
552
588
  :::
553
589
 
554
- ## Other
555
-
556
- By default, Modern.js will enable the built-in routing scheme, which is React Router.
557
-
558
- ```js
559
- export default defineConfig({
560
- runtime: {
561
- router: true,
562
- },
563
- });
564
- ```
565
-
566
- As mentioned above, when the [`runtime.router`](/configure/app/runtime/router) configuration is enabled, Modern.js will export the API of React Router from the `@modern-js/runtime/router` namespace for developers to use, ensuring that developers and Modern.js are using the same code, and automatically wrapping the `Provider` component according to the router configuration. In addition, in this case, the code of React Router will be packed into the JS output.
567
-
568
- If the project already has its own routing plan or does not need to use client-side routing, this feature can be disabled.
569
-
570
- ```js
571
- export default defineConfig({
572
- runtime: {
573
- router: false,
574
- },
575
- });
576
- ```
577
-
578
- As mentioned above, if the [`runtime.router`](/configure/app/runtime/router) configuration is disabled and `react-router-dom` is used directly for project routing management, the `Provider` needs to be wrapped according to the React Router documentation.
590
+ import Motivation from '@site-docs/components/convention-routing-motivation';