@modern-js/main-doc 2.0.0-beta.4 → 2.0.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/en/docusaurus-plugin-content-docs/current/apis/app/commands/dev.md +8 -3
- package/en/docusaurus-plugin-content-docs/current/apis/app/commands/inspect.md +33 -8
- package/en/docusaurus-plugin-content-docs/current/apis/app/commands/serve.md +32 -0
- package/en/docusaurus-plugin-content-docs/current/apis/app/hooks/src/server.md +31 -0
- package/en/docusaurus-plugin-content-docs/current/apis/app/runtime/core/bootstrap.md +4 -3
- package/en/docusaurus-plugin-content-docs/current/apis/app/runtime/core/create-app.md +2 -3
- package/en/docusaurus-plugin-content-docs/current/apis/app/runtime/core/use-module-apps.md +1 -1
- package/en/docusaurus-plugin-content-docs/current/components/init-app.md +1 -1
- package/en/docusaurus-plugin-content-docs/current/configure/app/builder-plugins.md +70 -0
- package/en/docusaurus-plugin-content-docs/current/configure/app/dev/with-master-app.md +0 -1
- package/en/docusaurus-plugin-content-docs/current/configure/app/plugins.md +11 -5
- package/en/docusaurus-plugin-content-docs/current/configure/app/source/disable-entry-dirs.md +38 -0
- package/en/docusaurus-plugin-content-docs/current/configure/app/source/entries.md +66 -2
- package/en/docusaurus-plugin-content-docs/current/configure/app/tools/esbuild.md +1 -1
- package/en/docusaurus-plugin-content-docs/current/guides/concept/entries.md +1 -1
- package/en/docusaurus-plugin-content-docs/current/guides/get-started/quick-start.md +3 -3
- package/en/docusaurus-plugin-content-docs/current/guides/topic-detail/framework-plugin/_category_.json +4 -0
- package/en/docusaurus-plugin-content-docs/current/guides/{concept → topic-detail/framework-plugin}/lifecycle.md +0 -0
- package/package.json +3 -3
- package/zh/apis/app/commands/dev.md +9 -4
- package/zh/apis/app/commands/inspect.md +34 -9
- package/zh/apis/app/commands/{start.md → serve.md} +3 -3
- package/zh/apis/app/hooks/src/index_.md +1 -1
- package/zh/apis/app/hooks/src/server.md +31 -0
- package/zh/apis/app/runtime/core/bootstrap.md +3 -4
- package/zh/apis/app/runtime/core/create-app.md +1 -18
- package/zh/apis/app/runtime/core/use-module-apps.md +64 -33
- package/zh/apis/app/runtime/web-server/hook.md +1 -1
- package/zh/apis/app/runtime/web-server/middleware.md +1 -0
- package/zh/components/default-mwa-generate.md +5 -0
- package/zh/components/deploy.md +1 -0
- package/zh/components/enable-micro-frontend.md +13 -0
- package/zh/components/init-app.md +2 -2
- package/zh/components/micro-runtime-config.md +18 -0
- package/zh/components/prerequisites.md +2 -2
- package/zh/components/release-note.md +1 -0
- package/zh/configure/app/builder-plugins.md +72 -0
- package/zh/configure/app/deploy/_category_.json +4 -0
- package/zh/configure/app/deploy/microFrontend.md +64 -0
- package/zh/configure/app/dev/with-master-app.md +0 -2
- package/zh/configure/app/plugins.md +10 -4
- package/zh/configure/app/runtime/master-app.md +33 -36
- package/zh/configure/app/source/disable-entry-dirs.md +37 -0
- package/zh/configure/app/source/entries-dir.md +0 -3
- package/zh/configure/app/source/entries.md +66 -3
- package/zh/guides/advanced-features/compatibility.md +12 -1
- package/zh/guides/advanced-features/eslint.md +21 -21
- package/zh/guides/advanced-features/ssg.md +14 -3
- package/zh/guides/advanced-features/ssr.md +1 -1
- package/zh/guides/advanced-features/testing.md +11 -0
- package/zh/guides/advanced-features/web-server.md +12 -1
- package/zh/guides/basic-features/css/tailwindcss.md +11 -0
- package/zh/guides/basic-features/data-fetch.md +398 -5
- package/zh/guides/basic-features/routes.md +35 -3
- package/zh/guides/concept/entries.md +104 -14
- package/zh/guides/get-started/quick-start.md +8 -5
- package/zh/guides/get-started/upgrade.md +3 -1
- package/zh/guides/{concept → topic-detail/framework-plugin}/lifecycle.md +0 -0
- package/zh/guides/topic-detail/micro-frontend/c01-introduction.md +29 -0
- package/zh/guides/topic-detail/micro-frontend/c02-development.md +191 -0
- package/zh/guides/topic-detail/micro-frontend/c03-main-app.md +246 -0
- package/zh/guides/topic-detail/micro-frontend/c04-communicate.md +54 -0
- package/zh/guides/topic-detail/micro-frontend/{mixed-stack.md → c05-mixed-stack.md} +3 -3
- package/zh/guides/topic-detail/monorepo/create-sub-project.md +2 -2
- package/zh/tutorials/first-app/c01-start.md +9 -4
- package/zh/tutorials/first-app/c03-css.md +19 -0
- package/zh/tutorials/first-app/c04-routes.md +4 -4
- package/zh/tutorials/first-app/c05-loader.md +3 -3
- package/zh/tutorials/first-app/c06-model.md +19 -19
- package/zh/tutorials/first-app/c07-container.md +38 -23
- package/zh/tutorials/first-app/c08-entries.md +4 -1
- package/en/docusaurus-plugin-content-docs/current/apis/app/commands/start.md +0 -32
- package/zh/guides/advanced-features/custom-app.md +0 -70
- package/zh/guides/topic-detail/micro-frontend/communicate.md +0 -39
- package/zh/guides/topic-detail/micro-frontend/debugging.md +0 -168
- package/zh/guides/topic-detail/micro-frontend/introduction.md +0 -13
- package/zh/guides/topic-detail/micro-frontend/route-mode.md +0 -110
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 1
|
|
3
|
+
title: 微前端介绍
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
微前端是一种类似于微服务的架构,是一种由独立交付的多个前端应用组成整体的架构风格,将前端应用分解成一些更小、更简单的能够独立开发、测试、部署的应用,而在用户看来仍然是内聚的单个产品。
|
|
7
|
+
|
|
8
|
+
它主要解决了两个问题:
|
|
9
|
+
|
|
10
|
+
* 随着项目迭代应用越来越庞大,难以维护。
|
|
11
|
+
* 跨团队或跨部门协作开发项目导致效率低下的问题。
|
|
12
|
+
|
|
13
|
+
## 微前端关键词
|
|
14
|
+
|
|
15
|
+
在微前端研发模式中,应用会被分成 **主应用**、和 **子应用**。
|
|
16
|
+
|
|
17
|
+
- 主应用:微前端项目的基座工程,所有子应用都会由它来加载。
|
|
18
|
+
- 子应用:独立开发、独立部署的应用,最终会被主应用加载。
|
|
19
|
+
|
|
20
|
+
## 功能简介
|
|
21
|
+
|
|
22
|
+
* 基于 [Garfish](https://www.garfishjs.org/guide)
|
|
23
|
+
* 生成器支持微前端应用
|
|
24
|
+
* 支持 React 组件式引用微前端子应用
|
|
25
|
+
* 支持 loading
|
|
26
|
+
* 支持主应用线上、子应用线下调试模式
|
|
27
|
+
|
|
28
|
+
可以在 [体验微前端](/docs/guides/topic-detail/micro-frontend/c02-development) 一节学习如何开发微前端主子应用。
|
|
29
|
+
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 2
|
|
3
|
+
title: 体验微前端
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
通过本章你可以了解到:
|
|
7
|
+
|
|
8
|
+
- 如何创建微前端项目的主应用、子应用。
|
|
9
|
+
- 微前端项目开发的基本流程。
|
|
10
|
+
|
|
11
|
+
## 创建应用
|
|
12
|
+
|
|
13
|
+
在这次的实践中,我们需要创建三个应用,分别为1个主应用,2个子应用:
|
|
14
|
+
|
|
15
|
+
- main 主应用
|
|
16
|
+
- dashboard 子应用
|
|
17
|
+
- table 子应用
|
|
18
|
+
|
|
19
|
+
### 创建 main 主应用
|
|
20
|
+
|
|
21
|
+
通过命令行工具初始化项目:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
mkdir main && cd main
|
|
25
|
+
npx @modern-js/create
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
import DefaultMWAGenerate from '@site-docs/components/default-mwa-generate.md';
|
|
29
|
+
|
|
30
|
+
<DefaultMWAGenerate />
|
|
31
|
+
|
|
32
|
+
完成项目创建后我们可以通过 `pnpm run new` 来开启 `微前端` 功能:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
? 请选择你想要的操作 启用可选功能
|
|
36
|
+
? 启用可选功能 启用「微前端」模式
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
接下来,让我们注册微前端插件并添加开启微前端主应用,并增加子应用列表:
|
|
40
|
+
|
|
41
|
+
import EnableMicroFrontend from '@site-docs/components/enable-micro-frontend.md';
|
|
42
|
+
|
|
43
|
+
<EnableMicroFrontend />
|
|
44
|
+
|
|
45
|
+
import MicroRuntimeConfig from '@site-docs/components/micro-runtime-config.md';
|
|
46
|
+
|
|
47
|
+
<MicroRuntimeConfig />
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
### 创建 dashboard 子应用
|
|
51
|
+
|
|
52
|
+
通过命令行工具初始化项目:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
mkdir dashboard && cd dashboard
|
|
56
|
+
npx @modern-js/create
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
按照如下选择,生成项目:
|
|
60
|
+
|
|
61
|
+
<DefaultMWAGenerate/>
|
|
62
|
+
|
|
63
|
+
我们执行 `pnpm run new` 来开启 `微前端` 功能:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
? 请选择你想要的操作 启用可选功能
|
|
67
|
+
? 启用可选功能 启用「微前端」模式
|
|
68
|
+
```
|
|
69
|
+
接下来,让我们注册微前端插件并修改 `modern.config.ts`,添加微前端子应用的配置 `deploy.microFrontend`:
|
|
70
|
+
|
|
71
|
+
```javascript title="modern.config.ts"
|
|
72
|
+
import AppToolPlugin, { defineConfig } from '@modern-js/app-tools';
|
|
73
|
+
import GarfishPlugin from '@modern-js/plugin-garfish';
|
|
74
|
+
|
|
75
|
+
export default defineConfig({
|
|
76
|
+
runtime: {
|
|
77
|
+
router: true,
|
|
78
|
+
state: true
|
|
79
|
+
},
|
|
80
|
+
deploy: {
|
|
81
|
+
microFrontend: true
|
|
82
|
+
},
|
|
83
|
+
plugins: [AppToolPlugin(), GarfishPlugin()],
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 创建 table 子应用
|
|
88
|
+
|
|
89
|
+
通过命令行工具初始化项目:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
mkdir table && cd table
|
|
93
|
+
npx @modern-js/create
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
按照如下选择,生成项目:
|
|
97
|
+
|
|
98
|
+
<DefaultMWAGenerate/>
|
|
99
|
+
|
|
100
|
+
我们执行 `pnpm run new` 来开启 `微前端`:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
? 请选择你想要的操作 启用可选功能
|
|
104
|
+
? 启用可选功能 启用「微前端」模式
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
接下来,让我们注册微前端插件并修改 `modern.config.ts`,添加微前端子应用的配置 `deploy.microFrontend`:
|
|
108
|
+
|
|
109
|
+
```javascript title="modern.config.ts"
|
|
110
|
+
import AppToolPlugin, { defineConfig } from '@modern-js/app-tools';
|
|
111
|
+
import GarfishPlugin from '@modern-js/plugin-garfish';
|
|
112
|
+
|
|
113
|
+
export default defineConfig({
|
|
114
|
+
runtime: {
|
|
115
|
+
router: true,
|
|
116
|
+
state: true
|
|
117
|
+
},
|
|
118
|
+
deploy: {
|
|
119
|
+
microFrontend: true
|
|
120
|
+
},
|
|
121
|
+
plugins: [AppToolPlugin(), GarfishPlugin()],
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## 添加代码
|
|
126
|
+
|
|
127
|
+
### main 主应用
|
|
128
|
+
|
|
129
|
+
删除 `src/routers` 目录, 创建 `src/App.tsx`,并添加如下内容:
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
import { Link } from '@modern-js/runtime/router';
|
|
133
|
+
import { useModuleApps } from '@modern-js/plugin-garfish/runtime';
|
|
134
|
+
|
|
135
|
+
const App = () => {
|
|
136
|
+
const { DashBoard, TableList } = useModuleApps();
|
|
137
|
+
return (
|
|
138
|
+
<div>
|
|
139
|
+
<div>
|
|
140
|
+
<Link to='/dashboard'>Dashboard</Link>
|
|
141
|
+
<Link to='/table'>Table</Link>
|
|
142
|
+
</div>
|
|
143
|
+
<Route path='/dashboard'>
|
|
144
|
+
<DashBoard />
|
|
145
|
+
</Route>
|
|
146
|
+
<Route path='/table'>
|
|
147
|
+
<TableList />
|
|
148
|
+
</Route>
|
|
149
|
+
</div>
|
|
150
|
+
);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export default App;
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### dashboard 子应用
|
|
157
|
+
|
|
158
|
+
删除 `src/routers` 目录, 创建 `src/App.tsx`,并添加如下内容:
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
export default () => <div>Dashboard Page</div>;
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### table 子应用
|
|
165
|
+
|
|
166
|
+
删除 `src/routers` 目录, 创建 `src/App.tsx`,并添加如下内容:
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
export default () => <div>Table Page</div>;
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## 调试
|
|
173
|
+
|
|
174
|
+
按顺序在 `main`、 `dashboard`、 `table` 目录执行 `pnpm run dev` 命令启动应用:
|
|
175
|
+
|
|
176
|
+
- main - `http://localhost:8080`
|
|
177
|
+
- dashboard - `http://localhost:8081`
|
|
178
|
+
- table - `http://localhost:8082`
|
|
179
|
+
|
|
180
|
+
访问主应用地址 `http://localhost:8080`,效果如下:
|
|
181
|
+
|
|
182
|
+

|
|
183
|
+
|
|
184
|
+
在完成了微前端整体开发流程的体验后,你可以进一步了解如何 [开发主应用](./c03-main-app.md)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
## 常见问题
|
|
188
|
+
|
|
189
|
+
自查手册: https://www.garfishjs.org/issues/
|
|
190
|
+
|
|
191
|
+
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 3
|
|
3
|
+
title: 开发主应用
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
在上一章 [体验微前端](./c02-development.md) 通过一个示例演示了如何创建和配置微前端子应用,通过本章你可以进一步了解如何开发主应用,以及它的常见配置。
|
|
7
|
+
|
|
8
|
+
在通过 `@modern-js/create` 命令创建应用工程后,可以在项目中执行 `pnpm run new`(实际执行了 `modern new` 命令),在选择了「微前端」模式后,会安装微前端依赖依赖,只需手动注册插件即可。
|
|
9
|
+
|
|
10
|
+
import EnableMicroFrontend from '@site-docs/components/enable-micro-frontend.md';
|
|
11
|
+
|
|
12
|
+
<EnableMicroFrontend />
|
|
13
|
+
|
|
14
|
+
## 注册子应用信息
|
|
15
|
+
|
|
16
|
+
当在 `masterApp` 配置上提供了信息后,将会认为该应用为主应用,目前存在两种子应用信息的配置方式,这两种方式分别应用于不同的场景。
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### 直接注册子应用信息
|
|
20
|
+
|
|
21
|
+
可以直接通过配置注册子应用信息:
|
|
22
|
+
|
|
23
|
+
:::tip 提示
|
|
24
|
+
可以通过 API [defineConfig](/docs/apis/app/runtime/app/define-config) 在运行时进行配置。
|
|
25
|
+
当参数为函数时无法被序列化到产物代码,所以在涉及到函数之类的配置时请通过 defineConfig 来进行配置
|
|
26
|
+
:::
|
|
27
|
+
|
|
28
|
+
import MicroRuntimeConfig from '@site-docs/components/micro-runtime-config.md';
|
|
29
|
+
|
|
30
|
+
<MicroRuntimeConfig />
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
### 自定义远程应用列表
|
|
34
|
+
|
|
35
|
+
通过该函数可以拉取远程的子应用列表,并将其注册至运行时框架:
|
|
36
|
+
|
|
37
|
+
```ts title="App.tsx"
|
|
38
|
+
defineConfig(App, {
|
|
39
|
+
masterApp: {
|
|
40
|
+
manifest: {
|
|
41
|
+
getAppList: async ()=> {
|
|
42
|
+
// 可以从其他远程接口获取
|
|
43
|
+
return [
|
|
44
|
+
{
|
|
45
|
+
name: 'DashBoard',
|
|
46
|
+
entry: 'http://127.0.0.1:8081/'
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'TableList',
|
|
50
|
+
entry: 'http://localhost:8082'
|
|
51
|
+
}
|
|
52
|
+
];
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 渲染子应用
|
|
60
|
+
|
|
61
|
+
在微前端中分为两种加载子应用的方式:
|
|
62
|
+
|
|
63
|
+
1. **子应用组件** 获取到每个子应用的组件,之后就可以像使用普通的 `React` 组件一样渲染微前端的子应用。
|
|
64
|
+
2. **集中式路由** 通过集中式的路由配置,自动根据当前页面 `pathname` 激活渲染对应的子应用。
|
|
65
|
+
|
|
66
|
+
### 子应用组件
|
|
67
|
+
|
|
68
|
+
开发者使用 `useModuleApps` 方法可以获取到各个子应用的组件。
|
|
69
|
+
|
|
70
|
+
再通过 `router` 组件的结合运用,开发者可以自控式的根据不同的路由渲染不同的子应用。
|
|
71
|
+
|
|
72
|
+
假设我们的子应用列表配置如下:
|
|
73
|
+
|
|
74
|
+
<EnableMicroFrontend />
|
|
75
|
+
|
|
76
|
+
编辑主应用 `App.tsx` 文件如下:
|
|
77
|
+
|
|
78
|
+
```tsx title=主应用:App.tsx
|
|
79
|
+
import { useModuleApps } from '@modern-js/plugin-garfish/runtime';
|
|
80
|
+
import { Route, Switch } from '@modern-js/runtime/router';
|
|
81
|
+
|
|
82
|
+
function App() {
|
|
83
|
+
const { DashBoard, TableList} = useModuleApps();
|
|
84
|
+
|
|
85
|
+
return <div>
|
|
86
|
+
<Route path="/dashboard">
|
|
87
|
+
<DashBoard
|
|
88
|
+
loadable={{
|
|
89
|
+
loading: ({ pastDelay, error }: any) => {
|
|
90
|
+
if (error) {
|
|
91
|
+
return <div>error: {error?.message}</div>;
|
|
92
|
+
} else if (pastDelay) {
|
|
93
|
+
return <div>loading</div>;
|
|
94
|
+
} else {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
}}
|
|
99
|
+
/>
|
|
100
|
+
</Route>
|
|
101
|
+
<Route path="/table">
|
|
102
|
+
<TableList />
|
|
103
|
+
</Route>
|
|
104
|
+
</div>
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
这里通过 `Route` 组件自定义了 **DashBoard** 的激活路由为 **/dashboard**, **TableList** 的激活路由为 **/table**。
|
|
109
|
+
|
|
110
|
+
### 集中式路由
|
|
111
|
+
|
|
112
|
+
**集中式路由** 是将子应用的激活路由集中配置的方式。我们给子应用列表信息添加 `activeWhen` 字段来启用 **集中式路由**。
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
<MicroRuntimeConfig />
|
|
116
|
+
|
|
117
|
+
然后在主应用中使用 `useModuleApp` 方法获取 `MApp` 组件, 并在主应用渲染 `MApp`。
|
|
118
|
+
|
|
119
|
+
```tsx title=主应用:App.tsx
|
|
120
|
+
import { useModuleApp } from '@modern-js/plugin-runtime';
|
|
121
|
+
|
|
122
|
+
function App() {
|
|
123
|
+
const { MApp } = useModuleApps();
|
|
124
|
+
|
|
125
|
+
return <div>
|
|
126
|
+
<MApp />
|
|
127
|
+
</div>
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
这样启动应用后,访问 `/dashboard` 路由,会渲染 `Dashboard` 子应用,访问 `/table` 路由,会渲染 `TableList` 子应用。
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
### 两种模式混用
|
|
135
|
+
|
|
136
|
+
当然 **子应用组件** 和 **集中式路由** 是可以混合使用的。
|
|
137
|
+
|
|
138
|
+
- 一部分子应用作为 **子应用组件** 激活,另外一部分作为 **集中式路由** 激活。
|
|
139
|
+
- 一部分子应用既可以作为 **集中式路由** 激活,也可以作为 **子应用组件** 激活。
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
### 添加 loading
|
|
143
|
+
|
|
144
|
+
通过配置 `loadable` 配置,可以为「集中式路由」、「子应用」添加 loading 组件,并可以考虑错误、超时、闪烁等情况的出现,从而为用户提供更好的用户体验。该功能的设计与实现参考至 [react-loadable](https://github.com/jamiebuilds/react-loadable),基本功能较为相似。
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
function Loading() {
|
|
148
|
+
return <div>Loading...</div>;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function App(){
|
|
152
|
+
return <>
|
|
153
|
+
<DashBoard
|
|
154
|
+
loadable={{
|
|
155
|
+
loading: Loading,
|
|
156
|
+
}}
|
|
157
|
+
/>
|
|
158
|
+
<>
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### 增加错误状态
|
|
163
|
+
|
|
164
|
+
当微前端子应用加载失败或渲染失败时,`loading component` 将会接收 `error` 参数(若没有错误时 error 是 null)
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
function Loading({ error }) {
|
|
168
|
+
if (error) {
|
|
169
|
+
return <div>Error msg {error?.message}</div>;
|
|
170
|
+
} else {
|
|
171
|
+
return <div>Loading...</div>;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
#### 避免 loading 闪退
|
|
177
|
+
|
|
178
|
+
有时 loading 组件的显示时间可能小于 200ms,这个时候会出现 loading 组件闪退的情况。许多用户研究证明,loading 闪退的情况会导致用户感知加载内容的耗时比实际耗时更长,在 loading 小于 200ms 时,不展示内容,用户会认为它更快。
|
|
179
|
+
|
|
180
|
+
所以 loading 组件还提供了 `pastDelay` 参数,超过设置的延迟展示时才会为 true,可以通过 `delay` 参数设置延迟的时长
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
function Loading({ error, pastDelay }) {
|
|
185
|
+
if (error) {
|
|
186
|
+
return <div>Error! {error?.message}</div>;
|
|
187
|
+
} else if (pastDelay) {
|
|
188
|
+
return <div>Loading...</div>;
|
|
189
|
+
} else {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
`delay` 的默认值为 `200ms`,可以通过 `loadable` 中的 `delay` 来设置延迟展示的时间
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
|
|
199
|
+
function App(){
|
|
200
|
+
return <>
|
|
201
|
+
<DashBoard
|
|
202
|
+
loadable={{
|
|
203
|
+
loading: Loading,
|
|
204
|
+
delay: 300 // 0.3 seconds
|
|
205
|
+
}}
|
|
206
|
+
/>
|
|
207
|
+
<>
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### 增加超时状态
|
|
212
|
+
|
|
213
|
+
有时因为网络的原因,从而导致微前端子应用加载失败,从而导致一直展示 loading 的状态,这对于用户而言非常糟糕,因为他们不知道合适才会获得具体的响应,他们是否需要刷新页面,通过增加超时状态可以很好的解决该问题。
|
|
214
|
+
|
|
215
|
+
loading 组件在超时时会获得 `timeOut` 参数,当微前端应用加载超时时将会获得 `timeOut` 属性值为 true
|
|
216
|
+
|
|
217
|
+
```tsx
|
|
218
|
+
function Loading({ error, timeOut, pastDelay }) {
|
|
219
|
+
if (error) {
|
|
220
|
+
return <div>Error! {error?.message}</div>;
|
|
221
|
+
} else if (timeOut) {
|
|
222
|
+
return <div>Loading timed out, please refresh the page... </div>;
|
|
223
|
+
} else if (pastDelay) {
|
|
224
|
+
return <div>Loading...</div>;
|
|
225
|
+
} else {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
超时状态是关闭的,可以通过在 `loadable` 中设置 `timeout` 参数开启
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
```tsx
|
|
235
|
+
|
|
236
|
+
function App(){
|
|
237
|
+
return <>
|
|
238
|
+
<DashBoard
|
|
239
|
+
loadable={{
|
|
240
|
+
loading: Loading,
|
|
241
|
+
timeOut: 10000 // 10s
|
|
242
|
+
}}
|
|
243
|
+
/>
|
|
244
|
+
<>
|
|
245
|
+
}
|
|
246
|
+
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 4
|
|
3
|
+
title: 主子应用通信
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## props 通信
|
|
7
|
+
|
|
8
|
+
Modern.js 中,会将子应用包裹成一个 React 组件,直接通过给 React 组件传递 `props` 即可实现主应用和子应用通信的目的。
|
|
9
|
+
|
|
10
|
+
```tsx title=主应用:App.tsx
|
|
11
|
+
function App() {
|
|
12
|
+
const { MApp } = useModuleApps();
|
|
13
|
+
|
|
14
|
+
return <div>
|
|
15
|
+
<MApp count={100} />
|
|
16
|
+
</div>;
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```tsx title=子应用:App.tsx
|
|
21
|
+
function App(props) {
|
|
22
|
+
console.log(props);
|
|
23
|
+
return ...
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
子应用将会打印 `{count: 0}`,目前尚未支持子应用渲染响应式,及时在主应用上更改 `count` 的数据也不会触发视图更新
|
|
28
|
+
|
|
29
|
+
## channel 通信
|
|
30
|
+
|
|
31
|
+
[Garfish.channel](https://www.garfishjs.org/api/channel) 用于应用间的通信。它是 `EventEmitter2` 的实例
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
// 子应用监听登录事件
|
|
35
|
+
const App = () => {
|
|
36
|
+
const handleLogin = (userInfo) => {
|
|
37
|
+
console.log(`${userInfo.name} has login`);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
window?.Garfish.channel.on('login', handleLogin);
|
|
42
|
+
return () => {
|
|
43
|
+
window?.Garfish.channel.removeListener('login', handleLogin);
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// 主应用触发监听事件
|
|
49
|
+
api.getLoginInfo.then((res) => {
|
|
50
|
+
if (res.code === 0) {
|
|
51
|
+
window.Garfish.channel.emit('login', res.data);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
```
|
|
@@ -3,7 +3,7 @@ sidebar_position: 5
|
|
|
3
3
|
title: 混合技术栈
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Modern.js 微前端方案是基于 [Garfish](https://
|
|
6
|
+
Modern.js 微前端方案是基于 [Garfish](https://garfishjs.org/) 封装的,提供了一些更开箱即用的使用方式。
|
|
7
7
|
|
|
8
8
|
当你的主应用和子应用不全是 Modern.js 应用的时候,可以参考这片文档。
|
|
9
9
|
|
|
@@ -12,7 +12,7 @@ Modern.js 微前端方案是基于 [Garfish](https://garfish.top/) 封装的,
|
|
|
12
12
|
|
|
13
13
|
## 子应用是 Modern.js
|
|
14
14
|
|
|
15
|
-
**Modern.js** 子应用编译后会生成标准的 [Garfish 子应用导出](https://
|
|
15
|
+
**Modern.js** 子应用编译后会生成标准的 [Garfish 子应用导出](https://www.garfishjs.org/guide/start#2%E5%AF%BC%E5%87%BA-provider-%E5%87%BD%E6%95%B0)。
|
|
16
16
|
所以可以直接接入标准的微前端主应用。
|
|
17
17
|
|
|
18
18
|
:::info 注
|
|
@@ -21,4 +21,4 @@ Modern.js 微前端方案是基于 [Garfish](https://garfish.top/) 封装的,
|
|
|
21
21
|
|
|
22
22
|
## 主应用是 Modern.js
|
|
23
23
|
|
|
24
|
-
主应用是 **Modern.js**,子应用用的其它技术栈。子应用按照 [Garfish 子应用标准](https://
|
|
24
|
+
主应用是 **Modern.js**,子应用用的其它技术栈。子应用按照 [Garfish 子应用标准](https://www.garfishjs.org/guide/demo/react) 开发即可。
|
|
@@ -57,8 +57,8 @@ pnpm run new
|
|
|
57
57
|
[INFO] 创建成功!
|
|
58
58
|
可在新项目的目录下运行以下命令:
|
|
59
59
|
pnpm run dev # 按开发环境的要求,运行和调试项目
|
|
60
|
-
pnpm run build #
|
|
61
|
-
pnpm run
|
|
60
|
+
pnpm run build # 按生产环境的要求,构建项目
|
|
61
|
+
pnpm run serve # 按生产环境的要求,运行项目
|
|
62
62
|
pnpm run lint # 检查和修复所有代码
|
|
63
63
|
pnpm run new # 继续创建更多项目要素,比如应用入口
|
|
64
64
|
```
|
|
@@ -64,20 +64,24 @@ function App() {
|
|
|
64
64
|
export default App;
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
因为框架默认支持 [HMR](https://webpack.js.org/concepts/hot-module-replacement/),可以看到 `http://localhost:8080/` 里的内容会自动变成 Hello Modern.js。
|
|
68
|
-
|
|
69
67
|
删除多余的 css 文件,保持目录没有多余的文件:
|
|
70
68
|
|
|
71
69
|
```bash
|
|
72
70
|
rm src/routes/index.css
|
|
73
71
|
```
|
|
74
72
|
|
|
75
|
-
|
|
73
|
+
因为框架默认支持 [HMR](https://webpack.js.org/concepts/hot-module-replacement/),可以看到 `http://localhost:8080/` 里的内容会自动更新为:
|
|
74
|
+
|
|
75
|
+

|
|
76
|
+
|
|
77
|
+
此刻的页面还没有样式。下一章节将展开这部分的内容。
|
|
78
|
+
|
|
79
|
+
## 开启 SSR
|
|
76
80
|
|
|
77
81
|
接下来,我们修改项目中的 `modern.config.ts`,开启 SSR 能力:
|
|
78
82
|
|
|
79
83
|
```ts
|
|
80
|
-
import { defineConfig } from '@modern-js/app-tools';
|
|
84
|
+
import AppToolsPlugin, { defineConfig } from '@modern-js/app-tools';
|
|
81
85
|
|
|
82
86
|
// https://modernjs.dev/docs/apis/app/config
|
|
83
87
|
export default defineConfig({
|
|
@@ -88,6 +92,7 @@ export default defineConfig({
|
|
|
88
92
|
server: {
|
|
89
93
|
ssr: true,
|
|
90
94
|
},
|
|
95
|
+
plugins: [AppToolsPlugin()],
|
|
91
96
|
});
|
|
92
97
|
```
|
|
93
98
|
|
|
@@ -118,6 +118,25 @@ Modern.js 集成了主流、轻量、通用的 Utility Class 工具库 [Tailwind
|
|
|
118
118
|
? 启用可选功能 启用 Tailwind CSS 支持
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
+
在 `modern.config.ts` 中注册 Tailwind 插件:
|
|
122
|
+
|
|
123
|
+
```ts title="modern.config.ts"
|
|
124
|
+
import AppToolsPlugin, { defineConfig } from '@modern-js/app-tools';
|
|
125
|
+
import TailwindCSSPlugin from '@modern-js/plugin-tailwindcss';
|
|
126
|
+
|
|
127
|
+
// https://modernjs.dev/docs/apis/app/config
|
|
128
|
+
export default defineConfig({
|
|
129
|
+
runtime: {
|
|
130
|
+
router: true,
|
|
131
|
+
state: true,
|
|
132
|
+
},
|
|
133
|
+
server: {
|
|
134
|
+
ssr: true,
|
|
135
|
+
},
|
|
136
|
+
plugins: [AppToolsPlugin(), TailwindCSSPlugin()],
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
121
140
|
在 `src/routes/page.tsx` 顶部引入 Tailwind CSS 的 css 文件,就可以开始快速实现专业的 UI:
|
|
122
141
|
|
|
123
142
|
```js
|
|
@@ -34,7 +34,7 @@ ni src/routes/archives/page.tsx
|
|
|
34
34
|
|
|
35
35
|
添加如下代码:
|
|
36
36
|
|
|
37
|
-
```tsx
|
|
37
|
+
```tsx title="src/archives/page.tsx"
|
|
38
38
|
import { List } from 'antd';
|
|
39
39
|
import { Helmet } from '@modern-js/runtime/head';
|
|
40
40
|
import Item from '../../components/Item';
|
|
@@ -94,16 +94,16 @@ Modern.js 默认集成了 react-helmet,也可以结合 SSR 使用,满足 SEO
|
|
|
94
94
|
import 'tailwindcss/base.css';
|
|
95
95
|
import 'tailwindcss/components.css';
|
|
96
96
|
import 'tailwindcss/utilities.css';
|
|
97
|
-
import
|
|
97
|
+
import '../styles/utils.css';
|
|
98
98
|
```
|
|
99
99
|
|
|
100
100
|
执行 `pnpm run dev`,访问 `http://localhost:8080`,可以看到完整的联系人,页面的标题是 All:
|
|
101
101
|
|
|
102
|
-

|
|
103
103
|
|
|
104
104
|
访问 `http://localhost:8080/archives`,只会看到已存档的联系人,页面的标题是 Archives:
|
|
105
105
|
|
|
106
|
-

|
|
107
107
|
|
|
108
108
|
查看页面 HTML 源码,可以看到两个页面的内容是一样,是在客户端针对不同 URL 渲染不同内容。
|
|
109
109
|
|
|
@@ -4,7 +4,7 @@ title: 添加 Loader
|
|
|
4
4
|
|
|
5
5
|
上一章节中,我们学习了如何添加客户端路由。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
这一章节中,我们将会学习如何为**路由组件添加 Loader**。
|
|
8
8
|
|
|
9
9
|
到目前为止,我们都是通过硬编码的方式,为组件提供数据。如果要从远端获取数据,通常情况下会使用 `useEffect` 来做。但在启用 SSR 的情况下,`useEffect` 是不会在服务端执行的,所以这种 SSR 只能渲染很有限的 UI。
|
|
10
10
|
|
|
@@ -20,7 +20,7 @@ pnpm add @types/faker@5 -D
|
|
|
20
20
|
修改 `src/routes/page.tsx`:
|
|
21
21
|
|
|
22
22
|
```tsx
|
|
23
|
-
import { name, internet } from
|
|
23
|
+
import { name, internet } from 'faker';
|
|
24
24
|
|
|
25
25
|
type LoaderData = {
|
|
26
26
|
code: number;
|
|
@@ -55,7 +55,7 @@ Data Loader 并非只为 SSR 工作。在 CSR 项目中,Data Loader 也可以
|
|
|
55
55
|
Modern.js 也提供了一个叫 `useLoaderData` 的 hooks API,我们修改 `src/routes/page.tsx` 导出的组件:
|
|
56
56
|
|
|
57
57
|
```tsx {1,4,13}
|
|
58
|
-
import { useLoaderData } from
|
|
58
|
+
import { useLoaderData } from '@modern-js/runtime/router';
|
|
59
59
|
|
|
60
60
|
function Index() {
|
|
61
61
|
const { data } = useLoaderData() as LoaderData;
|