@modern-js/main-doc 2.0.0-beta.4 → 2.0.0-beta.5
Sign up to get free protection for your applications and to get access to all the features.
- 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/runtime/garfish';
|
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/runtime/garfish';
|
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;
|