@modern-js/main-doc 2.19.2-alpha.0 → 2.21.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +25 -0
- package/docs/en/apis/app/runtime/router/router.mdx +22 -0
- package/docs/en/components/init-rspack-app.mdx +1 -1
- package/docs/en/components/ua-polyfill.mdx +40 -0
- package/docs/en/configure/app/output/temp-dir.mdx +24 -0
- package/docs/en/configure/app/security/nonce.mdx +13 -0
- package/docs/en/guides/advanced-features/compatibility.mdx +22 -40
- 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/get-started/quick-start.mdx +2 -2
- package/docs/en/guides/topic-detail/framework-plugin/extend.mdx +1 -1
- package/docs/en/guides/topic-detail/framework-plugin/hook-list.mdx +44 -4
- package/docs/en/guides/topic-detail/generator/codesmith/develop.mdx +1 -1
- package/docs/en/guides/topic-detail/generator/plugin/abstract.mdx +1 -1
- package/docs/en/guides/topic-detail/generator/plugin/develop.mdx +1 -1
- package/docs/en/guides/topic-detail/generator/plugin/use.mdx +1 -1
- package/docs/en/guides/topic-detail/generator/project.mdx +4 -4
- package/docs/en/guides/topic-detail/micro-frontend/c02-development.mdx +4 -4
- package/docs/en/tutorials/first-app/c01-start.mdx +1 -1
- package/docs/zh/apis/app/runtime/router/router.mdx +22 -0
- package/docs/zh/components/init-rspack-app.mdx +1 -1
- package/docs/zh/components/ua-polyfill.mdx +39 -0
- package/docs/zh/configure/app/output/temp-dir.mdx +22 -0
- package/docs/zh/configure/app/security/nonce.mdx +13 -0
- package/docs/zh/guides/advanced-features/compatibility.mdx +14 -51
- 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/get-started/quick-start.mdx +2 -2
- package/docs/zh/guides/topic-detail/changesets/changelog.mdx +1 -1
- package/docs/zh/guides/topic-detail/changesets/commit.mdx +1 -1
- package/docs/zh/guides/topic-detail/changesets/release-note.mdx +1 -1
- package/docs/zh/guides/topic-detail/framework-plugin/extend.mdx +1 -1
- package/docs/zh/guides/topic-detail/framework-plugin/hook-list.mdx +45 -5
- package/docs/zh/guides/topic-detail/generator/codesmith/develop.mdx +1 -1
- package/docs/zh/guides/topic-detail/generator/plugin/abstract.mdx +1 -1
- package/docs/zh/guides/topic-detail/generator/plugin/develop.mdx +1 -1
- package/docs/zh/guides/topic-detail/generator/plugin/use.mdx +1 -1
- package/docs/zh/guides/topic-detail/generator/project.mdx +4 -4
- package/docs/zh/guides/topic-detail/micro-frontend/c02-development.mdx +4 -4
- package/docs/zh/tutorials/first-app/c01-start.mdx +1 -1
- package/package.json +7 -7
- package/src/components/ShowcaseList/index.tsx +4 -4
@@ -10,7 +10,7 @@ Modern.js provides an initialization template that is versatile and can meet som
|
|
10
10
|
|
11
11
|
When you use Modern.js in depth, you will inevitably find that every time you create a project, you will make some similar changes specific to your own project, such as modifying the sample code, adding some configuration, enabling some functions, etc.
|
12
12
|
|
13
|
-
The generator plugin can help you precipitate these individual or team-specific changes. Simply bring the `--plugin` parameter when executing `npx @modern-js/create` to avoid the need to repeatedly modify the project every time the project is created..
|
13
|
+
The generator plugin can help you precipitate these individual or team-specific changes. Simply bring the `--plugin` parameter when executing `npx @modern-js/create@latest` to avoid the need to repeatedly modify the project every time the project is created..
|
14
14
|
|
15
15
|
The generator plugin is based on the initialization template project provided by the Modern.js, providing methods to add, delete and modify templates, and modifying `package.json`, `modernConfig` configuration and opening functions in a fast way.
|
16
16
|
|
@@ -9,7 +9,7 @@ sidebar_position: 3
|
|
9
9
|
Modern.js provides a generator plugin to create a generator plugin project, you can directly execute the following command to create:
|
10
10
|
|
11
11
|
```bash
|
12
|
-
npx @modern-js/create plugin --plugin @modern-js/generator-plugin-plugin
|
12
|
+
npx @modern-js/create@latest plugin --plugin @modern-js/generator-plugin-plugin
|
13
13
|
```
|
14
14
|
|
15
15
|
Different plugin types will ask different questions. You can choose the plugin type according to your needs.
|
@@ -9,7 +9,7 @@ sidebar_position: 2
|
|
9
9
|
You can use the generator plugin directly by executing the following command:
|
10
10
|
|
11
11
|
```bash
|
12
|
-
npx @modern-js/create --plugin <pluginName>
|
12
|
+
npx @modern-js/create@latest --plugin <pluginName>
|
13
13
|
```
|
14
14
|
|
15
15
|
The plugin parameter supports multiple declarations, which means that multiple generator plugins are used at the same time.
|
@@ -11,7 +11,7 @@ Modern.js provides `@modern-js/create` as a project generator for Modern.js proj
|
|
11
11
|
There is no need to install `@modern-js/create` globally, just execute the tool directly with npx:
|
12
12
|
|
13
13
|
```bash
|
14
|
-
npx @modern-js/create [projectDir]
|
14
|
+
npx @modern-js/create@latest [projectDir]
|
15
15
|
```
|
16
16
|
|
17
17
|
:::info
|
@@ -32,7 +32,7 @@ When executing the above command, the `projectDir` folder will be created in the
|
|
32
32
|
Get the `@modern-js/create` tool version.
|
33
33
|
|
34
34
|
```bash
|
35
|
-
$ npx @modern-js/create --version
|
35
|
+
$ npx @modern-js/create@latest --version
|
36
36
|
|
37
37
|
[INFO] @modern-js/create v2.0.0
|
38
38
|
```
|
@@ -52,7 +52,7 @@ By default, `@modern-js/create` will have interaction problems such as language
|
|
52
52
|
This field is a JSON character string, for example when running a package manager:
|
53
53
|
|
54
54
|
```bash
|
55
|
-
npx @modern-js/create --config '{"packageManager": "pnpm"}'
|
55
|
+
npx @modern-js/create@latest --config '{"packageManager": "pnpm"}'
|
56
56
|
```
|
57
57
|
|
58
58
|
Specific configuration information viewable [Project Configuration](/guides/topic-detail/generator/config/common).
|
@@ -105,7 +105,7 @@ For custom generator plugins, please refer to [Development Generator Plugin](/gu
|
|
105
105
|
|
106
106
|
Specifies the microgenerator.
|
107
107
|
|
108
|
-
By default, `@modern-js/create` will execute the microgenerator Modern.js framework build-in. If you need to execute a customized microgenerator, and you need to use the posture of `npx @modern-js/create`, you can use this parameter directly.
|
108
|
+
By default, `@modern-js/create` will execute the microgenerator Modern.js framework build-in. If you need to execute a customized microgenerator, and you need to use the posture of `npx @modern-js/create@latest`, you can use this parameter directly.
|
109
109
|
|
110
110
|
For custom microgenerators, please refer to [Develop Microgenerator](/guides/topic-detail/generator/codesmith/introduce).
|
111
111
|
|
@@ -27,7 +27,7 @@ Initialize the project with a command line:
|
|
27
27
|
|
28
28
|
```bash
|
29
29
|
mkdir masterApp && cd masterApp
|
30
|
-
npx @modern-js/create
|
30
|
+
npx @modern-js/create@latest
|
31
31
|
```
|
32
32
|
|
33
33
|
After the project is created, we can enable the `micro frontend` through `pnpm run new`:
|
@@ -109,7 +109,7 @@ Initialize the project with a command line:
|
|
109
109
|
|
110
110
|
```bash
|
111
111
|
mkdir masterApp && cd masterApp
|
112
|
-
npx @modern-js/create
|
112
|
+
npx @modern-js/create@latest
|
113
113
|
```
|
114
114
|
|
115
115
|
After the project is created, we can enable the `micro frontend` function through `pnpm run new`:
|
@@ -137,7 +137,7 @@ Initialize the project with a command line:
|
|
137
137
|
|
138
138
|
```bash
|
139
139
|
mkdir table && cd table
|
140
|
-
npx @modern-js/create
|
140
|
+
npx @modern-js/create@latest
|
141
141
|
```
|
142
142
|
|
143
143
|
After create sub-app. We execute `pnpm run new` to enable the `micro frontend` function:
|
@@ -186,7 +186,7 @@ Initialize the project with a command line:
|
|
186
186
|
|
187
187
|
```bash
|
188
188
|
mkdir table && cd table
|
189
|
-
npx @modern-js/create
|
189
|
+
npx @modern-js/create@latest
|
190
190
|
```
|
191
191
|
|
192
192
|
After create sub-app. We execute `pnpm run new` to enable the `micro frontend` function:
|
@@ -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,39 @@
|
|
1
|
+
### 运行时按需 Polyfill
|
2
|
+
|
3
|
+
Modern.js 中还提供了基于浏览器 [UA](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/User-Agent) 信息的运行时按需 Polyfill 方案,相比于 Babel 优势如下:
|
4
|
+
|
5
|
+
- 不会插入到代码中,只根据访问页面的设备,按需下发 Polyfill 代码 ,减少整体代码体积。
|
6
|
+
- 相同浏览器会公用一份 Polyfill 代码。因此,随着项目越来越多,基于 UA 的 Polyfill 代码下发速度会越来越快,综合速度超过常规方案。
|
7
|
+
|
8
|
+
可以通过微生成器开启该功能:
|
9
|
+
|
10
|
+
```bash
|
11
|
+
? 请选择你想要的操作 启用可选功能
|
12
|
+
? 启用可选功能 启用「基于 UA 的 Polyfill」功能
|
13
|
+
```
|
14
|
+
|
15
|
+
执行命令后,在 `modern.config.ts` 中注册 Polyfill 插件:
|
16
|
+
|
17
|
+
```ts title="modern.config.ts"
|
18
|
+
import polyfillPlugin from '@modern-js/plugin-polyfill';
|
19
|
+
|
20
|
+
export default defineConfig({
|
21
|
+
plugins: [..., polyfillPlugin()],
|
22
|
+
});
|
23
|
+
```
|
24
|
+
|
25
|
+
配置 `output.polyfill` 为 `ua` 并且执行 `pnpm run build && pnpm run serve` 启动服务器后,访问页面可以看到 HTML 产物中包含如下脚本:
|
26
|
+
|
27
|
+
```js
|
28
|
+
<script src="/__polyfill__" crossorigin></script>
|
29
|
+
```
|
30
|
+
|
31
|
+
在 Chrome 51 下访问页面可以看到 `http://localhost:8080/__polyfill__` 返回内容如下:
|
32
|
+
|
33
|
+

|
34
|
+
|
35
|
+
:::caution 注意
|
36
|
+
该功能只有在使用 Modern.js 内置的 Web Server 时才会生效。
|
37
|
+
|
38
|
+
如果有自定义模版的需求,请参考 [HTML 模板](/guides/basic-features/html.html)。通过 `html.template` 或 `tools.html` 手动修改模版时,可能会导致该功能无法正确生效。
|
39
|
+
:::
|
@@ -0,0 +1,22 @@
|
|
1
|
+
---
|
2
|
+
sidebar_label: tempDir
|
3
|
+
---
|
4
|
+
|
5
|
+
# output.tempDir
|
6
|
+
|
7
|
+
- **类型:** `string`
|
8
|
+
- **默认值:** `''`
|
9
|
+
|
10
|
+
项目开发或构建时,Modern.js 会生成真实的 Webpack 入口和 HTML 模板,并放在临时目录下。
|
11
|
+
|
12
|
+
如果希望由多个配置同时启动某项目,可以通过该配置,将文件生成到不同的临时目录下,避免相互干扰。配置可以是相对路径或绝对路径,但应避免项目外的路径。
|
13
|
+
|
14
|
+
示例
|
15
|
+
|
16
|
+
```ts
|
17
|
+
export default {
|
18
|
+
output: {
|
19
|
+
tempDir: path.join('node_modules', '.temp-dir'),
|
20
|
+
}
|
21
|
+
}
|
22
|
+
```
|
@@ -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 />
|
@@ -1,26 +1,25 @@
|
|
1
1
|
---
|
2
|
-
title: 客户端兼容性
|
3
2
|
sidebar_position: 5
|
4
3
|
---
|
5
|
-
|
4
|
+
|
5
|
+
# 浏览器兼容性
|
6
6
|
|
7
7
|
## Browserslist 配置
|
8
8
|
|
9
|
-
Modern.js
|
9
|
+
Modern.js 支持设置 Web 应用需要兼容的浏览器范围,你可以在 `.browserslistrc` 文件里设置 [Browserslist](https://browsersl.ist/) 的值。
|
10
10
|
|
11
|
-
Modern.js
|
11
|
+
当你创建一个新的 Modern.js 项目时,默认会包含一份 `.browserslistrc` 配置,这表示 JavaScript 代码会被编译至 ES6 格式。
|
12
12
|
|
13
|
-
```
|
14
|
-
|
13
|
+
```yaml title=".browserslistrc"
|
14
|
+
chrome >= 51
|
15
|
+
edge >= 15
|
16
|
+
firefox >= 54
|
17
|
+
safari >= 10
|
18
|
+
ios_saf >= 10
|
15
19
|
```
|
16
20
|
|
17
|
-
|
18
|
-
|
19
|
-
查看 Modern.js Builder 文档了解更多 [Browserslist](https://modernjs.dev/builder/guide/advanced/browserslist.html) 相关内容。
|
20
|
-
|
21
|
-
:::note
|
22
|
-
Modern.js 支持配置 [output.overrideBrowserslist](/configure/app/output/override-browserslist) 覆盖默认 browserslist 值。
|
23
|
-
|
21
|
+
:::tip
|
22
|
+
请查看 [Modern.js Builder - 设置浏览器范围](https://modernjs.dev/builder/guide/advanced/browserslist) 来了解更多内容。
|
24
23
|
:::
|
25
24
|
|
26
25
|
## Polyfill
|
@@ -36,42 +35,6 @@ Modern.js 在编译时默认通过 [core-js](https://github.com/zloirock/core-js
|
|
36
35
|
|
37
36
|
:::
|
38
37
|
|
39
|
-
|
40
|
-
|
41
|
-
Modern.js 中还提供了基于浏览器 [UA](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/User-Agent) 信息的运行时按需 Polyfill 方案,相比于 Babel 优势如下:
|
42
|
-
|
43
|
-
- 不会插入到代码中,只根据访问页面的设备,按需下发 Polyfill 代码 ,减少整体代码体积。
|
44
|
-
- 相同浏览器会公用一份 Polyfill 代码。因此,随着项目越来越多,基于 UA 的 Polyfill 代码下发速度会越来越快,综合速度超过常规方案。
|
45
|
-
|
46
|
-
可以通过微生成器开启该功能:
|
47
|
-
|
48
|
-
```bash
|
49
|
-
? 请选择你想要的操作 启用可选功能
|
50
|
-
? 启用可选功能 启用「基于 UA 的 Polyfill」功能
|
51
|
-
```
|
52
|
-
|
53
|
-
执行命令后,在 `modern.config.ts` 中注册 Polyfill 插件:
|
38
|
+
import UAPolyfill from '@site-docs/components/ua-polyfill';
|
54
39
|
|
55
|
-
|
56
|
-
import polyfillPlugin from '@modern-js/plugin-polyfill';
|
57
|
-
|
58
|
-
export default defineConfig({
|
59
|
-
plugins: [..., polyfillPlugin()],
|
60
|
-
});
|
61
|
-
```
|
62
|
-
|
63
|
-
配置 `output.polyfill` 为 `ua` 并且执行 `pnpm run build && pnpm run serve` 启动服务器后,访问页面可以看到 HTML 产物中包含如下脚本:
|
64
|
-
|
65
|
-
```js
|
66
|
-
<script src="/__polyfill__" crossorigin></script>
|
67
|
-
```
|
68
|
-
|
69
|
-
在 Chrome 51 下访问页面可以看到 `http://localhost:8080/__polyfill__` 返回内容如下:
|
70
|
-
|
71
|
-

|
72
|
-
|
73
|
-
:::caution 注意
|
74
|
-
该功能只有在使用 Modern.js 内置的 Web Server 时才会生效。
|
75
|
-
|
76
|
-
如果有自定义模版的需求,请参考 [HTML 模板](/guides/basic-features/html.html)。通过 `html.template` 或 `tools.html` 手动修改模版时,可能会导致该功能无法正确生效。
|
77
|
-
:::
|
40
|
+
<UAPolyfill />
|
@@ -58,3 +58,40 @@ import appTools, { defineConfig } from '@modern-js/app-tools';
|
|
58
58
|
:::tip
|
59
59
|
从 webpack 迁移至 Rspack 时,存在一些构建能力和配置上的差异,详情可参考:[配置差异](https://modernjs.dev/builder/guide/advanced/rspack-start.html#从-webpack-迁移到-rspack)
|
60
60
|
:::
|
61
|
+
|
62
|
+
## Rspack 和 Modern.js 的版本关系
|
63
|
+
|
64
|
+
通常情况下,Modern.js 内会集成 Rspack 的最新版本,通过 `npx modern upgrade` 即可将当前项目中的 Modern.js 相关依赖以及内置的 Rspack 更新至最新版本。
|
65
|
+
|
66
|
+
但 Modern.js 对于 Rspack 的依赖方式为锁版本方式(非自动升级),由于发版周期不同步等原因,可能会出现 Modern.js 内集成的 Rspack 版本落后于 Rspack 最新版本的情况。
|
67
|
+
|
68
|
+
当你执行 dev / build 命令时,Modern.js 会自动打印当前使用的 Rspack 版本:
|
69
|
+
|
70
|
+

|
71
|
+
|
72
|
+
#### 修改内置 Rspack 版本
|
73
|
+
|
74
|
+
可以使用 pnpm / yarn / npm 等包管理工具自带的依赖升级功能来将 Rspack 强制升级到指定版本。
|
75
|
+
|
76
|
+
以 pnpm 为例,可通过 `overrides` 以下依赖更新 Rspack 版本:
|
77
|
+
|
78
|
+
```json title=package.json
|
79
|
+
{
|
80
|
+
"pnpm": {
|
81
|
+
"overrides": {
|
82
|
+
"@rspack/core": "nightly",
|
83
|
+
"@rspack/dev-client": "nightly",
|
84
|
+
"@rspack/dev-middleware": "nightly",
|
85
|
+
"@rspack/plugin-html": "nightly",
|
86
|
+
"@rspack/postcss-loader": "nightly"
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
```
|
91
|
+
|
92
|
+
:::tip Nightly 版本介绍
|
93
|
+
每天,Rspack 会自动构建基于最新代码的 nightly 版本,用于测试和及早发现错误。
|
94
|
+
通常情况下,这些版本是可用的。如果发现问题,我们会及时进行修复。但是,如果 Rspack 有一些 break change,需要 Modern.js 同步修改代码,那么我们建议等待下一个 Modern.js 版本再进行更新。
|
95
|
+
:::
|
96
|
+
|
97
|
+
如果想了解其他包管理工具锁定依赖版本的示例,可以参考:[锁定子依赖](/guides/get-started/upgrade.html#%E9%94%81%E5%AE%9A%E5%AD%90%E4%BE%9D%E8%B5%96)。
|
@@ -14,7 +14,7 @@ Modern.js 中提供了开箱即用的数据获取能力,开发者可以通过
|
|
14
14
|
Modern.js 推荐使用约定式路由做路由的管理,通过 Modern.js 的[约定式(嵌套)路由](/guides/basic-features/routes#约定式路由),每个路由组件(`layout.ts` 或 `page.ts`)可以有一个同名的 `loader` 文件,该 `loader` 文件需要导出一个函数,函数会在组件渲染之前执行,为路由组件提供数据。
|
15
15
|
|
16
16
|
:::info
|
17
|
-
Modern.js v1 支持通过 [useLoader](#useloader
|
17
|
+
Modern.js v1 支持通过 [useLoader](#useloader(旧版)) 获取数据,这已经不是我们推荐的用法,除迁移过程外,不推荐两者混用。
|
18
18
|
|
19
19
|
:::
|
20
20
|
|
@@ -22,7 +22,7 @@ Modern.js v1 支持通过 [useLoader](#useloader旧版) 获取数据,这已经
|
|
22
22
|
|
23
23
|
路由组件如 `layout.ts` 或 `page.ts`,可以定义同名的 `loader` 文件,`loader` 文件中导出一个函数,该函数提供组件所需的数据,然后在路由组件中通过 `useLoaderData` 函数获取数据,如下面示例:
|
24
24
|
|
25
|
-
```
|
25
|
+
```bash
|
26
26
|
.
|
27
27
|
└── routes
|
28
28
|
├── layout.tsx
|
@@ -66,19 +66,19 @@ export default async (): Promise<ProfileData> => {
|
|
66
66
|
在 SSR 环境下,不管是首屏,还是在客户端的导航,`loader` 函数只会在服务端执行,这里可以调用任意的 Node.js API,同时这里使用的任何依赖和代码都不会包含在客户端的 bundle 中。
|
67
67
|
|
68
68
|
:::info
|
69
|
-
在以后的版本中,Modern.js 可能会支持在 CSR 环境下,`loader` 函数也在服务端运行,以提高性能和安全性,所以这里建议尽可能地保证 loader 的纯粹,只做数据获取的场景。
|
69
|
+
在以后的版本中,Modern.js 可能会支持在 CSR 环境下,`loader` 函数也在服务端运行,以提高性能和安全性,所以这里建议尽可能地保证 `loader` 的纯粹,只做数据获取的场景。
|
70
70
|
|
71
71
|
:::
|
72
72
|
|
73
|
-
当在客户端导航时,基于 Modern.js 的[约定式路由](/guides/basic-features/routes),所有的 loader 函数会并行执行(请求),即当访问 `/user/profile` 时,`/user` 和 `/user/profile` 下的 loader 函数都会并行执行(请求),以提高客户端的性能。
|
73
|
+
当在客户端导航时,基于 Modern.js 的[约定式路由](/guides/basic-features/routes),所有的 `loader` 函数会并行执行(请求),即当访问 `/user/profile` 时,`/user` 和 `/user/profile` 下的 loader 函数都会并行执行(请求),以提高客户端的性能。
|
74
74
|
|
75
75
|
### `loader` 函数
|
76
76
|
|
77
77
|
`loader` 函数有两个入参:
|
78
78
|
|
79
|
-
#### `
|
79
|
+
#### `params`
|
80
80
|
|
81
|
-
当路由文件通过 `[]` 时,会作为[动态路由](/guides/basic-features/routes#动态路由),动态路由片段会作为参数传入 loader 函数:
|
81
|
+
当路由文件通过 `[]` 时,会作为[动态路由](/guides/basic-features/routes#动态路由),动态路由片段会作为参数传入 `loader` 函数:
|
82
82
|
|
83
83
|
```tsx
|
84
84
|
// routes/user/[id]/page.loader.ts
|
@@ -149,7 +149,7 @@ async function loader() {
|
|
149
149
|
|
150
150
|
### 错误处理
|
151
151
|
|
152
|
-
在 `loader` 函数中,可以通过 `throw error` 或者 `throw response` 的方式处理错误,当 `loader` 函数中有错误被抛出时,Modern.js 会停止执行当前 loader 中的代码,并将前端 UI 切换到定义的 [`ErrorBoundary`](/guides/basic-features/routes#错误处理) 组件:
|
152
|
+
在 `loader` 函数中,可以通过 `throw error` 或者 `throw response` 的方式处理错误,当 `loader` 函数中有错误被抛出时,Modern.js 会停止执行当前 `loader` 中的代码,并将前端 UI 切换到定义的 [`ErrorBoundary`](/guides/basic-features/routes#错误处理) 组件:
|
153
153
|
|
154
154
|
```tsx
|
155
155
|
// routes/user/profile/page.loader.ts
|
@@ -178,14 +178,14 @@ export default ErrorBoundary;
|
|
178
178
|
|
179
179
|
### 获取上层组件的数据
|
180
180
|
|
181
|
-
很多场景下,子组件需要获取到祖先组件 loader 中的数据,你可以通过 `useRouteLoaderData` 方便地获取到祖先组件的数据:
|
181
|
+
很多场景下,子组件需要获取到祖先组件 `loader` 中的数据,你可以通过 `useRouteLoaderData` 方便地获取到祖先组件的数据:
|
182
182
|
|
183
183
|
```tsx
|
184
184
|
// routes/user/profile/page.tsx
|
185
185
|
import { useRouteLoaderData } from '@modern-js/runtime/router';
|
186
186
|
|
187
187
|
export default function UserLayout() {
|
188
|
-
// 获取 routes/user/layout.loader.ts 中 loader 返回的数据
|
188
|
+
// 获取 routes/user/layout.loader.ts 中 `loader` 返回的数据
|
189
189
|
const data = useRouteLoaderData('user/layout');
|
190
190
|
return (
|
191
191
|
<div>
|
@@ -198,7 +198,7 @@ export default function UserLayout() {
|
|
198
198
|
|
199
199
|
`userRouteLoaderData` 接受一个参数 `routeId`,在使用约定式路由时,Modern.js 会为你自动生成`routeId`,`routeId` 的值是对应组件相对于 `src/routes` 的路径,如上面的例子中,子组件想要获取 `routes/user/layout.tsx` 中 loader 返回的数据,`routeId` 的值就是 `user/layout`。
|
200
200
|
|
201
|
-
|
201
|
+
在多入口(MPA) 场景下,`routeId` 的值需要加上对应入口的名称,入口名称非指定情况下一般是入口的目录名,如以下目录结构:
|
202
202
|
|
203
203
|
```bash
|
204
204
|
.
|
@@ -211,7 +211,7 @@ export default function UserLayout() {
|
|
211
211
|
└── layout.tsx
|
212
212
|
```
|
213
213
|
|
214
|
-
如果想获取 `entry1/routes/layout.tsx` 中 loader 返回的数据,`routeId` 的值就是 `entry1_layout`。
|
214
|
+
如果想获取 `entry1/routes/layout.tsx` 中 `loader` 返回的数据,`routeId` 的值就是 `entry1_layout`。
|
215
215
|
|
216
216
|
### (WIP)Loading UI
|
217
217
|
|
@@ -341,11 +341,11 @@ export default async (): Promise<ProfileData> => {
|
|
341
341
|
|
342
342
|
### 常见问题
|
343
343
|
|
344
|
-
1. loader 和 BFF 函数的关系
|
344
|
+
1. `loader` 和 BFF 函数的关系
|
345
345
|
|
346
|
-
在 CSR
|
346
|
+
在 CSR 项目中,`loader` 在客户端执行,在 `loader` 可以直接调用 BFF 函数进行接口请求。
|
347
347
|
|
348
|
-
在 SSR 项目中,每个 loader 也是一个服务端接口,我们推荐使用 loader 替代 http method 为 `get` 的 BFF 函数,作为接口层,避免多一层转发和执行。
|
348
|
+
在 SSR 项目中,每个 `loader` 也是一个服务端接口,我们推荐使用 `loader` 替代 http method 为 `get` 的 BFF 函数,作为接口层,避免多一层转发和执行。
|
349
349
|
|
350
350
|
|
351
351
|
## useLoader(旧版)
|
@@ -18,7 +18,7 @@ Modern.js 的路由基于 [React Router 6](https://reactrouter.com/en/main),
|
|
18
18
|
|
19
19
|
Modern.js 支持了业界流行的约定式路由模式:**嵌套路由**,使用嵌套路由时,页面的路由 与 UI 结构是相呼应的,我们将会详细介绍这种路由模式。
|
20
20
|
|
21
|
-
```
|
21
|
+
```bash
|
22
22
|
/user/johnny/profile /user/johnny/posts
|
23
23
|
+------------------+ +-----------------+
|
24
24
|
| User | | User |
|
@@ -154,7 +154,7 @@ export default () => {
|
|
154
154
|
|
155
155
|
通过 `[]` 命名的文件目录,生成的路由会作为动态路由。例如以下文件目录:
|
156
156
|
|
157
|
-
```
|
157
|
+
```bash
|
158
158
|
└── routes
|
159
159
|
├── [id]
|
160
160
|
│ └── page.tsx
|
@@ -173,7 +173,7 @@ export default () => {
|
|
173
173
|
|
174
174
|
通过 `[$]` 命名的文件目录,生成的路由会作为动态路由。例如以下文件目录:
|
175
175
|
|
176
|
-
```
|
176
|
+
```bash
|
177
177
|
└── routes
|
178
178
|
├── user
|
179
179
|
│ └── [id$]
|
@@ -199,7 +199,7 @@ export default () => {
|
|
199
199
|
|
200
200
|
例如以下目录结构:
|
201
201
|
|
202
|
-
```
|
202
|
+
```bash
|
203
203
|
└── routes
|
204
204
|
├── $.tsx
|
205
205
|
├── blog
|
@@ -222,7 +222,7 @@ params['*']; // => 'aaa/bbb'
|
|
222
222
|
|
223
223
|
当目录名以 \_\_ 开头时,对应的目录名不会转换为实际的路由路径,例如以下文件目录:
|
224
224
|
|
225
|
-
```
|
225
|
+
```bash
|
226
226
|
.
|
227
227
|
└── routes
|
228
228
|
├── __auth
|
@@ -245,7 +245,7 @@ Modern.js 会生成 `/login` 和 `/sign` 两条路由,`__auth/layout.tsx` 组
|
|
245
245
|
|
246
246
|
因此 Modern.js 支持了通过 `.` 来分割路由片段,代替文件目录。例如,当需要 `/user/profile/2022/edit` 时,可以直接创建如下文件:
|
247
247
|
|
248
|
-
```
|
248
|
+
```bash
|
249
249
|
└── routes
|
250
250
|
├── user.profile.[id].edit
|
251
251
|
│ └── page.tsx
|
@@ -281,7 +281,7 @@ Modern.js 会生成 `/login` 和 `/sign` 两条路由,`__auth/layout.tsx` 组
|
|
281
281
|
|
282
282
|
当定义 `loading.tsx` 时,就相当于以下布局:
|
283
283
|
|
284
|
-
```tsx title
|
284
|
+
```tsx title=当路由为"/"时
|
285
285
|
<Layout>
|
286
286
|
<Suspense fallback={<Loading />}>
|
287
287
|
<Page />
|
@@ -289,7 +289,7 @@ Modern.js 会生成 `/login` 和 `/sign` 两条路由,`__auth/layout.tsx` 组
|
|
289
289
|
</Layout>
|
290
290
|
```
|
291
291
|
|
292
|
-
```tsx title
|
292
|
+
```tsx title=当路由为"/blog"时
|
293
293
|
<Layout>
|
294
294
|
<Suspense fallback={<Loading />}>
|
295
295
|
<BlogPage />
|
@@ -297,7 +297,7 @@ Modern.js 会生成 `/login` 和 `/sign` 两条路由,`__auth/layout.tsx` 组
|
|
297
297
|
</Layout>
|
298
298
|
```
|
299
299
|
|
300
|
-
```tsx title
|
300
|
+
```tsx title=当路由为"/blog/123"时
|
301
301
|
<Layout>
|
302
302
|
<Suspense fallback={<Loading />}>
|
303
303
|
<BlogIdPage />
|
@@ -306,8 +306,8 @@ Modern.js 会生成 `/login` 和 `/sign` 两条路由,`__auth/layout.tsx` 组
|
|
306
306
|
```
|
307
307
|
|
308
308
|
:::info
|
309
|
-
当目录的
|
310
|
-
Modern.js 建议必须有根
|
309
|
+
当目录的 Layout 组件不存在时,该目录下的 Loading 组件也不会生效。
|
310
|
+
Modern.js 建议必须有根 Layout 和根 Loading。
|
311
311
|
|
312
312
|
:::
|
313
313
|
|
@@ -317,7 +317,7 @@ Modern.js 建议必须有根 layout 和根 loading。
|
|
317
317
|
|
318
318
|
### 路由重定向
|
319
319
|
|
320
|
-
可以通过创建 [`
|
320
|
+
可以通过创建 [`Data Loader`](/guides/basic-features/data-fetch) 文件做路由的重定向,如有文件 `routes/user/page.tsx`,想对这个文件对应的路由做重定向,可以创建 `routes/user/page.loader.ts` 文件:
|
321
321
|
|
322
322
|
```ts title="routes/user/page.loader.ts"
|
323
323
|
import { redirect } from '@modern-js/runtime/router';
|
@@ -335,13 +335,13 @@ export default () => {
|
|
335
335
|
|
336
336
|
`routes/` 下每一层目录中,开发者同样可以定义一个 `error.tsx` 文件,默认导出一个 `<ErrorBoundary>` 组件。
|
337
337
|
|
338
|
-
当有路由目录下存在该组件时,组件渲染出错会被 ErrorBoundary 组件捕获。当目录未定义 `layout.tsx` 文件时,`<ErrorBoundary>` 组件不会生效。
|
338
|
+
当有路由目录下存在该组件时,组件渲染出错会被 `ErrorBoundary` 组件捕获。当目录未定义 `layout.tsx` 文件时,`<ErrorBoundary>` 组件不会生效。
|
339
339
|
|
340
340
|
`<ErrorBoundary>` 可以返回出错时的 UI 视图,当前层级未声明 `<ErrorBoundary>` 组件时,错误会向上冒泡到更上层的组件,直到被捕获或抛出错误。同时,当组件出错时,只会影响捕获到该错误的路由组件及子组件,其他组件的状态和视图不受影响,可以继续交互。
|
341
341
|
|
342
342
|
{/* Todo API 路由 */}
|
343
343
|
|
344
|
-
在 `<ErrorBoundary>` 组件内,可以使用 [useRouteError](/apis/app/runtime/router/router#
|
344
|
+
在 `<ErrorBoundary>` 组件内,可以使用 [useRouteError](/apis/app/runtime/router/router#userouteerror) 获取的错误的具体信息:
|
345
345
|
|
346
346
|
```tsx
|
347
347
|
import { useRouteError } from '@modern-js/runtime/router';
|
@@ -359,7 +359,7 @@ export default ErrorBoundary;
|
|
359
359
|
|
360
360
|
### 运行时配置
|
361
361
|
|
362
|
-
在每个根 `Layout` 组件中(`routes/layout.ts`)
|
362
|
+
在每个根 `Layout` 组件中(`routes/layout.ts`),可以动态地定义运行时配置:
|
363
363
|
|
364
364
|
```tsx title="src/routes/layout.tsx"
|
365
365
|
// 定义运行时配置
|
@@ -447,29 +447,29 @@ export const init = (context: RuntimeContext) => {
|
|
447
447
|
### 预加载
|
448
448
|
|
449
449
|
在约定式路由下, Modern.js 会根据路由,自动地对路由进行分片,当用户访问具体的路由时,会自动加载对应的分片,这样可以有效地减少首屏加载的时间。但这也带来了一个问题,当用户访问一个路由时,如果该路由对应的分片还未加载完成,就会出现白屏的情况。
|
450
|
-
这种情况下你可以通过定义 `
|
450
|
+
这种情况下你可以通过定义 `Loading` 组件,在静态资源加载完成前,展示一个自定义的 `Loading` 组件。
|
451
451
|
|
452
452
|
为了进一步提升用户体验,减少 loading 的时间,Modern.js 支持在 Link 组件上定义 `prefetch` 属性,可以提前对静态资源和数据进行加载, `prefetch` 属性有三个可选值:
|
453
453
|
|
454
|
-
```
|
454
|
+
```tsx
|
455
455
|
<Link prefetch="intent" to="page">
|
456
456
|
```
|
457
457
|
|
458
458
|
:::info
|
459
459
|
- 该功能目前仅在 Webpack 项目中支持,Rspack 项目暂不支持。
|
460
|
-
- 对数据的预加载目前只会预加载 SSR 项目中 [
|
460
|
+
- 对数据的预加载目前只会预加载 SSR 项目中 [Data Loader](/guides/basic-features/data-fetch) 中返回的数据。
|
461
461
|
|
462
462
|
:::
|
463
463
|
|
464
464
|
- `none`, 默认值,不会做 prefetch,没有任何额外的行为。
|
465
|
-
- `intent`,这是我们推荐大多数场景下使用的值,当你把鼠标放在 Link 上时,会自动开始加载对应的分片和
|
466
|
-
- `render`,当 Link 组件渲染时,就会加载对应的分片和
|
465
|
+
- `intent`,这是我们推荐大多数场景下使用的值,当你把鼠标放在 Link 上时,会自动开始加载对应的分片和 Data Loader 中定义的数据,当鼠标移开时,会自动取消加载。在我们的测试中,即使是快速点击,也能减少大约 200ms 的加载时间。
|
466
|
+
- `render`,当 Link 组件渲染时,就会加载对应的分片和 Data Loader 中定义的数据。
|
467
467
|
|
468
468
|
#### 常见问题
|
469
469
|
|
470
470
|
1. 使用 `render` 和不根据路由做静态资源分片的区别?
|
471
471
|
|
472
|
-
- 使用 `render` 可以指定哪些路由在首屏时,进行加载,同时你可以通过对渲染的控制,仅当 Link 组件进入到可视区域时,才对 Link 组件进行渲染。
|
472
|
+
- 使用 `render` 可以指定哪些路由在首屏时,进行加载,同时你可以通过对渲染的控制,仅当 `Link` 组件进入到可视区域时,才对 `Link` 组件进行渲染。
|
473
473
|
- 使用 `render`,仅在空闲时对静态资源进行加载,不会与首屏静态资源抢占网络。
|
474
474
|
- 在 SSR 场景下,也会对数据进行预取。
|
475
475
|
|
@@ -484,7 +484,7 @@ import Practice from '@site-docs/components/routes-practice'
|
|
484
484
|
|
485
485
|
## 自控式路由
|
486
486
|
|
487
|
-
以 `src/App.tsx` 为约定的入口,Modern.js
|
487
|
+
以 `src/App.tsx` 为约定的入口,Modern.js 不会对路由做额外的操作,开发者可以自行使用 [React Router 6](https://reactrouter.com/en/main) 的 API 进行开发,例如:
|
488
488
|
|
489
489
|
```ts title="src/App.tsx"
|
490
490
|
import { BrowserRouter, Route, Routes } from '@modern-js/runtime/router';
|
@@ -18,13 +18,13 @@ Modern.js 提供了 `@modern-js/create` 生成器来创建项目,不要全局
|
|
18
18
|
|
19
19
|
```bash
|
20
20
|
mkdir myapp && cd myapp
|
21
|
-
npx @modern-js/create
|
21
|
+
npx @modern-js/create@latest
|
22
22
|
```
|
23
23
|
|
24
24
|
也可以直接用新目录创建项目:
|
25
25
|
|
26
26
|
```bash
|
27
|
-
npx @modern-js/create myapp
|
27
|
+
npx @modern-js/create@latest myapp
|
28
28
|
```
|
29
29
|
|
30
30
|
## 初始化项目
|