@modern-js/main-doc 0.0.0-next-20221227140603 → 0.0.0-next-20221228051706

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.
Files changed (23) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +2 -27
  3. package/en/docusaurus-plugin-content-docs/current/apis/app/runtime/router/router.md +176 -373
  4. package/en/docusaurus-plugin-content-docs/current/components/enable-bff.md +36 -0
  5. package/en/docusaurus-plugin-content-docs/current/components/router-legacy-tip.md +1 -0
  6. package/en/docusaurus-plugin-content-docs/current/configure/app/runtime/router.md +17 -2
  7. package/en/docusaurus-plugin-content-docs/current/guides/advanced-features/bff/frameworks.md +2 -0
  8. package/en/docusaurus-plugin-content-docs/current/guides/advanced-features/bff/function.md +10 -6
  9. package/en/docusaurus-plugin-content-docs/current/guides/basic-features/data-fetch.md +1 -0
  10. package/en/docusaurus-plugin-content-docs/current/guides/basic-features/routes.md +0 -2
  11. package/package.json +3 -3
  12. package/zh/apis/app/runtime/router/router.md +170 -368
  13. package/zh/components/enable-bff.md +36 -0
  14. package/zh/components/micro-master-manifest-config.md +15 -0
  15. package/zh/components/router-legacy-tip.md +1 -0
  16. package/zh/configure/app/runtime/master-app.md +2 -16
  17. package/zh/configure/app/runtime/router.md +17 -3
  18. package/zh/guides/advanced-features/bff/frameworks.md +2 -0
  19. package/zh/guides/advanced-features/bff/function.md +7 -5
  20. package/zh/guides/basic-features/data-fetch.md +1 -0
  21. package/zh/guides/basic-features/routes.md +0 -3
  22. package/en/docusaurus-plugin-content-docs/current/configure/app/dev/with-master-app.md +0 -31
  23. package/zh/configure/app/dev/with-master-app.md +0 -32
@@ -4,31 +4,43 @@ sidebar_position: 1
4
4
  ---
5
5
 
6
6
  :::info 补充信息
7
- 基于 [react-router](https://reactrouter.com/web/guides/start) 的路由解决方案。
7
+ 基于 [react-router](https://reactrouter.com/) 的路由解决方案。
8
8
  :::
9
9
 
10
10
  :::caution 注意
11
- 使用该 API 前,请确认没有禁用 [router 插件](#)。
11
+ 使用该 API 前,请确认没有禁用 [router 插件](/docs/configure/app/runtime/router)。
12
12
  :::
13
13
 
14
14
  ## hooks
15
15
 
16
- ### useHistory
16
+ ### useNavigate
17
17
 
18
18
  ```ts
19
- function useHistory<HistoryLocationState = H.LocationState>(): H.History<HistoryLocationState>;
19
+ declare function useNavigate(): NavigateFunction;
20
+
21
+ interface NavigateFunction {
22
+ (
23
+ to: To,
24
+ options?: {
25
+ replace?: boolean;
26
+ state?: any;
27
+ relative?: RelativeRoutingType;
28
+ }
29
+ ): void;
30
+ (delta: number): void;
31
+ }
20
32
  ```
21
33
 
22
- 用于获取 `history` 实例。
34
+ `useNavigate` 返回一个可以用于执行导航操作的函数。
23
35
 
24
36
  ```tsx
25
- import { useHistory } from "@modern-js/runtime/router";
37
+ import { useNavigate } from "@modern-js/runtime/router";
26
38
 
27
39
  export function HomeButton() {
28
- let history = useHistory();
40
+ let navigate = useNavigate();
29
41
 
30
42
  function handleClick() {
31
- history.push("/home");
43
+ navigate("/home");
32
44
  }
33
45
 
34
46
  return (
@@ -42,20 +54,18 @@ export function HomeButton() {
42
54
  ### useLocation
43
55
 
44
56
  ```ts
45
- function useLocation<S = H.LocationState>(): H.Location<S>;
57
+ declare function useLocation(): Location;
58
+
59
+ interface Location extends Path {
60
+ state: unknown;
61
+ key: Key;
62
+ }
46
63
  ```
47
64
 
48
65
  `useLocation` 返回当前 url 对应的 [location](https://reactrouter.com/web/api/location) 对象。每当路由更新的时候,都会拿到一个新的 `location` 对象。
49
66
 
50
67
  ```ts
51
- import React from "react";
52
- import { bootstrap, createApp } from '@modern-js/runtime';
53
- import { router } from '@modern-js/runtime/plugins';
54
- import {
55
- BrowserRouter as Router,
56
- Switch,
57
- useLocation
58
- } from "@modern-js/runtime/router";
68
+ import { useLocation } from "@modern-js/runtime/router";
59
69
 
60
70
  function usePageViews() {
61
71
  let location = useLocation();
@@ -66,24 +76,23 @@ function usePageViews() {
66
76
 
67
77
  function App() {
68
78
  usePageViews();
69
- return <Switch>...</Switch>;
79
+ return (
80
+ //...
81
+ );
70
82
  }
71
83
  ```
72
84
 
73
85
  ### useParams
74
86
 
75
87
  ```ts
76
- function useParams<
77
- Params extends {
78
- [K in keyof Params]?: string
79
- } = {}
80
- >(): Params;
88
+ declare function useParams<
89
+ K extends string = string
90
+ >(): Readonly<Params<K>>;
81
91
  ```
82
92
 
83
- `useParams` 返回一个 key/value 的键值对表示路由中的参数信息。它等同于 `<Route >` 组件中的 `match.params` 值。
93
+ `useParams` 返回一个 key/value 的键值对,表示当前匹配的路由 `<Route path>` 中的参数信息。
84
94
 
85
95
  ```tsx
86
- import React from "react";
87
96
  import {
88
97
  Switch,
89
98
  Route,
@@ -96,44 +105,34 @@ function BlogPost() {
96
105
  }
97
106
 
98
107
  function App() {
99
- return <Switch>
100
- <Route exact path="/">
101
- <div>home</div>
102
- </Route>
103
- <Route path="/blog/:slug">
104
- <BlogPost />
105
- </Route>
106
- </Switch>
108
+ return (
109
+ <Routes>
110
+ <Route path="/" element={ <div>home</div> } />
111
+ <Route path="/blog/:slug" element={ <BlogPost />}/>
112
+ </Routes>
113
+ )
107
114
  }
108
115
  ```
109
116
 
110
- ### useRouteMatch
111
-
112
- ```ts
113
- function useRouteMatch<
114
- Params extends { [K in keyof Params]?: string } = {}
115
- >(): match<Params>;
116
-
117
- function useRouteMatch<
118
- Params extends { [K in keyof Params]?: string } = {}
119
- >(
120
- path: string | string[] | RouteProps,
121
- ): match<Params> | null;
122
- ```
123
-
124
- `useRouteMatch` 和 `<Route />` 一样是对路由进行匹配,但无须去渲染 `<Route />` 组件,便能获取到当前匹配结果。
125
-
126
117
  ## 组件
127
118
 
128
-
129
-
130
119
  ### Link
131
120
 
132
121
  ```ts
133
- interface Link<S = H.LocationState>
134
- extends React.ForwardRefExoticComponent<
135
- React.PropsWithoutRef<LinkProps<S>> & React.RefAttributes<HTMLAnchorElement>
136
- > {}
122
+ declare function Link(props: LinkProps): React.ReactElement;
123
+
124
+ interface LinkProps
125
+ extends Omit<
126
+ React.AnchorHTMLAttributes<HTMLAnchorElement>,
127
+ "href"
128
+ > {
129
+ replace?: boolean;
130
+ state?: any;
131
+ to: To;
132
+ reloadDocument?: boolean;
133
+ }
134
+
135
+ type To = string | Partial<Path>;
137
136
  ```
138
137
 
139
138
  可以使用 `Link` 组件进行路由跳转。
@@ -142,351 +141,154 @@ interface Link<S = H.LocationState>
142
141
  <Link to="/about">About</Link>
143
142
  ```
144
143
 
145
- #### LinkProps
146
-
147
- **to**
148
-
149
- 类型:`string | object | function`
150
-
151
- `string`
152
-
153
- ```ts
154
- <Link to="/courses?sort=name" />
155
- ```
156
-
157
- `object`
158
-
159
- ```tsx
160
- <Link
161
- to={{
162
- pathname: "/courses",
163
- search: "?sort=name",
164
- hash: "#the-hash",
165
- state: { fromDashboard: true }
166
- }}
167
- />
168
- ```
169
-
170
- `function`
171
-
172
- ```tsx
173
- <Link to={location => ({ ...location, pathname: "/courses" })} />
174
-
175
- <Link to={location => `${location.pathname}?sort=name`} />
176
- ```
177
-
178
- **replace**
179
-
180
- 类型:`boolean`
181
-
182
- 当设置为 `true` 时,在跳转的时候替换掉 history 栈中的栈顶路由,而不是添加一个新路由。
183
-
184
- **component**
185
-
186
- 类型:`Component`
187
-
188
- 如果你想自定义你自己的路由跳转的组件,可以通过传入 `component` 来实现。
189
-
190
- ```tsx
191
- simply do so by passing it through the component prop.const FancyLink = React.forwardRef((props, ref) => (
192
- <a ref={ref} {...props}>💅 {props.children}</a>
193
- ))
194
-
195
- <Link to="/" component={FancyLink} />
196
- ```
197
-
198
144
  ### NavLink
199
145
 
200
146
  ```ts
201
- interface NavLink<S = H.LocationState>
202
- extends React.ForwardRefExoticComponent<
203
- React.PropsWithoutRef<NavLinkProps<S>> & React.RefAttributes<HTMLAnchorElement>
204
- > {}
205
- ```
206
-
207
- `NavLink` 是一种特殊的 [Link](#link) 组件,当 `NavLink` 对应路由匹配到当前 `url`, 会给 `NavLink` 所渲染的元素添加一些额外的样式。
208
-
209
-
210
- #### NavLinkProps
211
-
212
- **activeClassName**
213
-
214
- 类型:`string`
215
-
216
- 设置路由匹配时额外 class。
217
-
218
- ```tsx
219
- <NavLink to="/faq" activeClassName="selected">
220
- FAQs
221
- </NavLink>
222
- ```
223
-
224
- **activeStyle**
225
-
226
- 类型:`object`
227
-
228
- 设置路由匹配时额外的样式。
229
-
230
- ```tsx
231
- <NavLink
232
- to="/faq"
233
- activeStyle={{
234
- fontWeight: "bold",
235
- color: "red"
236
- }}
237
- >
238
- FAQs
239
- </NavLink>
240
- ```
241
-
242
- **exact**
243
-
244
- 类型:`boolean`
245
-
246
-
247
- **strict**
248
-
249
- 类型:`boolean`
250
-
251
- **isActive**
252
-
253
- 类型:`function`
254
-
255
- 如果你想自定义当前 Link 是否激活的逻辑,可以使用 `isActive`。
256
-
257
- ```tsx
258
- <NavLink
259
- to="/events/123"
260
- isActive={(match, location) => {
261
- if (!match) {
262
- return false;
263
- }
264
-
265
- // only consider an event active if its event id is an odd number
266
- const eventID = parseInt(match.params.eventID);
267
- return !isNaN(eventID) && eventID % 2 === 1;
268
- }}
269
- >
270
- Event 123
271
- </NavLink>
272
- ```
273
-
274
- **location**
275
-
276
- 类型:`object`
277
-
278
- `NavLink` 默认会和当前的 `history.location` 进行匹配,判断是否处于激活状态。如果你想指定要匹配的 `location` 对象,可以使用该参数。
279
-
280
- **area-current**
281
-
282
- 类型:`string`
283
-
284
- 参考 [aria-current](https://www.w3.org/TR/wai-aria-1.1/#aria-current)
285
-
286
-
287
-
288
- ### Prompt
289
-
290
- ```ts
291
- interface PromptProps {
292
- message: string | ((location: H.Location, action: H.Action) => string | boolean);
293
- when?: boolean;
147
+ declare function NavLink(
148
+ props: NavLinkProps
149
+ ): React.ReactElement;
150
+
151
+ interface NavLinkProps
152
+ extends Omit<
153
+ LinkProps,
154
+ "className" | "style" | "children"
155
+ > {
156
+ caseSensitive?: boolean;
157
+ children?:
158
+ | React.ReactNode
159
+ | ((props: { isActive: boolean }) => React.ReactNode);
160
+ className?:
161
+ | string
162
+ | ((props: {
163
+ isActive: boolean;
164
+ }) => string | undefined);
165
+ end?: boolean;
166
+ style?:
167
+ | React.CSSProperties
168
+ | ((props: {
169
+ isActive: boolean;
170
+ }) => React.CSSProperties);
294
171
  }
295
-
296
- class Prompt extends React.Component<PromptProps, any> {}
297
- ```
298
-
299
- `Prompt` 组件可用于在页面跳转前,进行二次确认是否跳转。
300
-
301
- ```tsx
302
- <Prompt
303
- when={formIsHalfFilledOut}
304
- message="Are you sure you want to leave?"
305
- />
306
172
  ```
307
173
 
308
- #### PromptProps
309
-
310
- **message**
311
-
312
- 类型:`string` | `function`
313
-
314
- 在页面跳转前的二次确认提示信息,支持传入函数形式。
315
-
316
- ```tsx
317
- <Prompt
318
- message={(location, action) => {
319
- if (action === 'POP') {
320
- console.log("Backing up...")
321
- }
322
-
323
- return location.pathname.startsWith("/app")
324
- ? true
325
- : `Are you sure you want to go to ${location.pathname}?`
326
- }}
327
- />
328
- ```
174
+ `<NavLink>` 是一种特殊的 `<Link>`,当 `<NavLink>` 对应的链接和当前 URL 匹配时,会给 `<NavLink>` 所渲染的元素添加“激活”态样式。
329
175
 
330
- **when**
331
176
 
332
- 类型:`boolean`
333
-
334
- 当 `when` 为 `true` 时,才会在页面跳转前展示二次确认提示。
335
-
336
-
337
- ### Route
177
+ ### Outlet
338
178
 
339
179
  ```ts
340
- interface RouteProps<
341
- Path extends string = string,
342
- Params extends { [K: string]: string | undefined } = ExtractRouteParams<Path, string>
343
- > {
344
- location?: H.Location;
345
- component?: React.ComponentType<RouteComponentProps<any>> | React.ComponentType<any>;
346
- render?: (props: RouteComponentProps<Params>) => React.ReactNode;
347
- children?: ((props: RouteChildrenProps<Params>) => React.ReactNode) | React.ReactNode;
348
- path?: Path | Path[];
349
- exact?: boolean;
350
- sensitive?: boolean;
351
- strict?: boolean;
180
+ interface OutletProps {
181
+ context?: unknown;
352
182
  }
353
-
354
- class Route<T extends {} = {}, Path extends string = string> extends React.Component<
355
- RouteProps<Path> & OmitNative<T, keyof RouteProps>,
356
- any
357
- > {}
183
+ declare function Outlet(
184
+ props: OutletProps
185
+ ): React.ReactElement | null;
358
186
  ```
359
187
 
360
- `Route` 组件用于定义路由。
361
-
362
- #### component
363
-
364
- 类型:`React.ComponentType`
365
-
366
- 当路由匹配成功,会渲染传入 `component` 的组件。
188
+ `<Outlet>` 用于嵌套路由场景。在父路由的元素中使用,代表待渲染的子路由的元素在父组件中的位置。
367
189
 
368
190
  ```tsx
369
- import React from "react";
370
- import { Route } from "@modern-js/runtime/router";
371
-
372
- // All route props (match, location and history) are available to User
373
- function User(props) {
374
- return <h1>Hello {props.match.params.username}!</h1>;
191
+ function Dashboard() {
192
+ return (
193
+ <div>
194
+ <h1>Dashboard</h1>
195
+
196
+ {/* This element will render either <DashboardMessages> when the URL is
197
+ "/messages", <DashboardTasks> at "/tasks", or null if it is "/"
198
+ */}
199
+ <Outlet />
200
+ </div>
201
+ );
375
202
  }
376
203
 
377
204
  function App() {
378
- return <Route path="/user/:username" component={User} />;
205
+ return (
206
+ <Routes>
207
+ <Route path="/" element={<Dashboard />}>
208
+ <Route
209
+ path="messages"
210
+ element={<DashboardMessages />}
211
+ />
212
+ <Route path="tasks" element={<DashboardTasks />} />
213
+ </Route>
214
+ </Routes>
215
+ );
379
216
  }
380
217
  ```
381
218
 
382
- :::tip 提示
383
- 如果 component 是一个 inline function,如 `<Route path="/user/:username" component={() => 'hello'} />`,因为每次 rerender 的时候,component 都会是一个新的 `type`,所以 component 组件会先 unmount,再 mount。我们需要避免这种写法,或者使用 render 代替 component。
384
- :::
385
-
386
- #### render
387
-
388
- 类型:`(props: RouteComponentProps<Params>) => React.ReactNode`
389
-
390
- 允许使用 `inline function` 进行渲染,同时不会有 `component` remounting 的问题。
391
-
392
- ```tsx
393
- import React from "react";
394
- import { Route } from "@modern-js/runtime/router";
219
+ ### Route
395
220
 
396
- function App() {
397
- <Route path="/home" render={() => <div>Home</div>} />
221
+ ```ts
222
+ interface RouteObject {
223
+ path?: string;
224
+ index?: boolean;
225
+ children?: React.ReactNode;
226
+ caseSensitive?: boolean;
227
+ id?: string;
228
+ loader?: LoaderFunction;
229
+ action?: ActionFunction;
230
+ element?: React.ReactNode | null;
231
+ errorElement?: React.ReactNode | null;
232
+ handle?: RouteObject["handle"];
233
+ shouldRevalidate?: ShouldRevalidateFunction;
398
234
  }
399
235
  ```
400
236
 
401
- :::info
402
- component 的优先级高于 render。
403
- :::
237
+ `Route` 用于定义路由。一个 `Route` 对象,将 URL 片段和组件、数据获取关联起来。
404
238
 
405
- #### children
239
+ `Route` 可以作为普通对象,传给创建 router 的函数的参数:
406
240
 
407
- 类型:`((props: RouteChildrenProps<Params>) => React.ReactNode) | React.ReactNode`
241
+ ```ts
242
+ const router = createBrowserRouter([
243
+ {
244
+ // it renders this element
245
+ element: <Team />,
246
+
247
+ // when the URL matches this segment
248
+ path: "teams/:teamId",
249
+
250
+ // with this data loaded before rendering
251
+ loader: async ({ request, params }) => {
252
+ return fetch(
253
+ `/fake/api/teams/${params.teamId}.json`,
254
+ { signal: request.signal }
255
+ );
256
+ },
257
+
258
+ // performing this mutation when data is submitted to it
259
+ action: async ({ request }) => {
260
+ return updateFakeTeam(await request.formData());
261
+ },
262
+
263
+ // and renders this element in case something went wrong
264
+ errorElement: <ErrorBoundary />,
265
+ },
266
+ ]);
267
+ ```
408
268
 
409
- 如果在路由匹配或不匹配的情况下,都需要渲染一些内容,那么可以使用 `children` 参数。
269
+ `Route` 还可以作为组件使用,通过 `createRoutesFromElements` 转换后,再传给创建 router 的函数的参数:
410
270
 
411
- ```tsx
412
- function ListItemLink({ to, ...rest }) {
413
- return (
271
+ ```ts
272
+ const router = createBrowserRouter(
273
+ createRoutesFromElements(
414
274
  <Route
415
- path={to}
416
- children={({ match }) => (
417
- <li className={match ? "active" : ""}>
418
- <Link to={to} {...rest} />
419
- </li>
420
- )}
275
+ element={<Team />}
276
+ path="teams/:teamId"
277
+ loader={async ({ params }) => {
278
+ return fetch(
279
+ `/fake/api/teams/${params.teamId}.json`
280
+ );
281
+ }}
282
+ action={async ({ request }) => {
283
+ return updateFakeTeam(await request.formData());
284
+ }}
285
+ errorElement={<ErrorBoundary />}
421
286
  />
422
- );
423
- }
424
-
425
- function App() {
426
- return <ul>
427
- <ListItemLink to="/somewhere" />
428
- <ListItemLink to="/somewhere-else" />
429
- </ul>;
430
- }
431
- ```
432
-
433
- #### path
434
-
435
- 类型:`string | string[]`
436
-
437
- 符合 [path-to-regexp@^1.7.0](https://github.com/pillarjs/path-to-regexp/tree/v1.7.0) 匹配规则的 url 字符串或数组。
438
-
439
- ```tsx
440
- <Route path="/users/:id">
441
- <User />
442
- </Route>
443
-
444
- <Route path={["/users/:id", "/profile/:id"]}>
445
- <User />
446
- </Route>
287
+ )
288
+ );
447
289
  ```
448
290
 
449
- #### exact
450
-
451
- 类型:`boolean`
452
-
453
- 默认值:`false`
454
-
455
- 当 `exact` 值为 `true` 时,会进行准确匹配。
456
-
457
- | path | location.pathname | exact | matches? |
458
- | - | - | - | - |
459
- | /one | /one/two | true | no |
460
- | /one | /one/two | false | yes |
461
-
462
-
463
- #### strict
464
-
465
- 类型:`boolean`
466
-
467
- 默认值:`false`
468
-
469
- 当 `strict` 值为 `true` 时,会进行严格匹配。若 `path` 以 '/' 结尾,那么 `location.pathname` 也需要以 '/' 结尾,才能匹配。
470
-
471
- | path | location.pathname | matches? |
472
- | - | - | - |
473
- | /one/ | /one | no |
474
- | /one/ | /one/ | yes |
475
- | /one/| /one/two | yes |
476
-
477
- #### sensitive
478
-
479
- 类型:`boolean`
480
-
481
- 默认值:`false`
482
-
483
- 当 `sensitive` 设置为 `true`,则 path 大小写不敏感。
484
-
485
- #### location
486
-
487
- 类型:`object`
488
-
489
- ## 更多底层 API
291
+ ## 更多 API
490
292
 
491
- 若想要了解更多的底层 API 信息,可至 [react-router 官网](https://reactrouter.com/web/guides/start) 查看。
293
+ 若想要了解完整的路由 API 信息,可至 [react-router 官网](https://reactrouter.com/web/guides/start) 查看。
492
294
 
@@ -0,0 +1,36 @@
1
+ 1. 执行 `pnpm new`,选择启用 BFF
2
+ 2. 根据选择的运行时框架,将下面的代码添加到 `modern.config.[tj]s` 中:
3
+
4
+ import Tabs from '@theme/Tabs';
5
+ import TabItem from '@theme/TabItem';
6
+
7
+ <Tabs>
8
+ <TabItem value="express" label="Express.js" default>
9
+
10
+ ```ts title="edenx.config.ts"
11
+ import ExpressPlugin from '@edenx/plugin-express';
12
+ import BffPlugin from '@edenx/plugin-bff';
13
+
14
+ export default defineConfig({
15
+ plugins: [
16
+ ExpressPlugin(),
17
+ BffPlugin()
18
+ ]
19
+ })
20
+ ```
21
+ </TabItem>
22
+ <TabItem value="koa" label="Koa.js">
23
+
24
+ ```ts title="edenx.config.ts"
25
+ import KoaPlugin from '@edenx/plugin-koa';
26
+ import BffPlugin from '@edenx/plugin-bff';
27
+
28
+ export default defineConfig({
29
+ plugins: [
30
+ KoaPlugin(),
31
+ BffPlugin()
32
+ ]
33
+ })
34
+ ```
35
+ </TabItem>
36
+ </Tabs>
@@ -0,0 +1,15 @@
1
+ ## `manifest`
2
+
3
+ ```ts
4
+ interface Manifest {
5
+ getAppList?: ()=> Array<AppInfo>
6
+ }
7
+ ```
8
+
9
+ ### `getAppList?`
10
+
11
+ 通过 `getAppList` 配置,可以自定义如何获取远程列表数据
12
+
13
+ ```ts
14
+ type GetAppList = ()=> Promise<Array<AppInfo>>;
15
+ ```
@@ -0,0 +1 @@
1
+