@ice/mf-runtime 0.0.4 → 0.0.6-beta.1
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/README.md +57 -3
- package/es2017/RemoteModule.d.ts +3 -3
- package/es2017/mf-global-store.js +10 -2
- package/esm/RemoteModule.d.ts +3 -3
- package/esm/mf-global-store.js +10 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -207,6 +207,26 @@ RemoteConfig 配置:
|
|
|
207
207
|
|
|
208
208
|
### RemoteModule
|
|
209
209
|
|
|
210
|
+
RemoteModule 组件支持泛型,可以用来约束远程组件的 props 类型:
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
// 定义远程组件的 props 类型
|
|
214
|
+
interface RemoteButtonProps {
|
|
215
|
+
onClick: () => void;
|
|
216
|
+
text: string;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// 使用带类型的 RemoteModule
|
|
220
|
+
<RemoteModule<RemoteButtonProps>
|
|
221
|
+
module="Button"
|
|
222
|
+
scope="remote_app"
|
|
223
|
+
componentProps={{
|
|
224
|
+
onClick: () => console.log('clicked'),
|
|
225
|
+
text: '点击我'
|
|
226
|
+
}}
|
|
227
|
+
/>
|
|
228
|
+
```
|
|
229
|
+
|
|
210
230
|
组件属性:
|
|
211
231
|
|
|
212
232
|
| 参数 | 说明 | 类型 | 默认值 |
|
|
@@ -218,9 +238,32 @@ RemoteConfig 配置:
|
|
|
218
238
|
| LoadingComponent | 加载状态组件 | `ReactNode` | `<div>Loading...</div>` |
|
|
219
239
|
| ErrorComponent | 错误回退组件 | `ReactNode` | `<div>远程模块加载失败: {error.message}</div>` |
|
|
220
240
|
| onError | 错误处理回调函数 | `(error: Error, info: { componentStack: string }) => void` | - |
|
|
221
|
-
| componentProps | 传递给远程模块的属性 | `object` | `{}` |
|
|
241
|
+
| componentProps | 传递给远程模块的属性 | `T extends object` | `{}` |
|
|
222
242
|
| children | 传递给远程模块的子元素 | `ReactNode` | `null` |
|
|
223
243
|
|
|
244
|
+
类型定义:
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
// RemoteModule 的类型定义
|
|
248
|
+
interface RemoteModuleOptions<T = any> {
|
|
249
|
+
module: string;
|
|
250
|
+
scope: string;
|
|
251
|
+
runtime?: {
|
|
252
|
+
react: typeof import('react');
|
|
253
|
+
reactDOM: typeof import('react-dom');
|
|
254
|
+
};
|
|
255
|
+
publicPath?: string;
|
|
256
|
+
LoadingComponent?: React.ReactNode;
|
|
257
|
+
ErrorComponent?: React.ReactNode;
|
|
258
|
+
onError?: (error: Error, info: { componentStack: string }) => void;
|
|
259
|
+
componentProps?: T;
|
|
260
|
+
children?: React.ReactNode;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// 组件声明
|
|
264
|
+
const RemoteModule = <T extends object = any>(props: RemoteModuleOptions<T>) => { ... }
|
|
265
|
+
```
|
|
266
|
+
|
|
224
267
|
|
|
225
268
|
## 注意事项
|
|
226
269
|
|
|
@@ -236,11 +279,22 @@ RemoteConfig 配置:
|
|
|
236
279
|
```tsx
|
|
237
280
|
import { RemoteModule } from '@ice/mf-runtime';
|
|
238
281
|
|
|
282
|
+
interface UserProfileProps {
|
|
283
|
+
userId: string;
|
|
284
|
+
showAvatar: boolean;
|
|
285
|
+
onUserClick: (user: any) => void;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
interface CardProps {
|
|
289
|
+
title: string;
|
|
290
|
+
children?: React.ReactNode;
|
|
291
|
+
}
|
|
292
|
+
|
|
239
293
|
function App() {
|
|
240
294
|
return (
|
|
241
295
|
<div>
|
|
242
296
|
{/* 传递属性示例 */}
|
|
243
|
-
<RemoteModule
|
|
297
|
+
<RemoteModule<UserProfileProps>
|
|
244
298
|
module="UserProfile"
|
|
245
299
|
scope="remote_app"
|
|
246
300
|
componentProps={{
|
|
@@ -251,7 +305,7 @@ function App() {
|
|
|
251
305
|
/>
|
|
252
306
|
|
|
253
307
|
{/* 传递子元素示例 */}
|
|
254
|
-
<RemoteModule
|
|
308
|
+
<RemoteModule<CardProps>
|
|
255
309
|
module="Card"
|
|
256
310
|
scope="remote_app"
|
|
257
311
|
componentProps={{
|
package/es2017/RemoteModule.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
interface RemoteModuleOptions {
|
|
2
|
+
interface RemoteModuleOptions<T = any> {
|
|
3
3
|
module: string;
|
|
4
4
|
scope: string;
|
|
5
5
|
runtime?: {
|
|
@@ -12,8 +12,8 @@ interface RemoteModuleOptions {
|
|
|
12
12
|
onError?: (error: Error, info: {
|
|
13
13
|
componentStack: string;
|
|
14
14
|
}) => void;
|
|
15
|
-
componentProps?:
|
|
15
|
+
componentProps?: T;
|
|
16
16
|
children?: React.ReactNode;
|
|
17
17
|
}
|
|
18
|
-
export declare const RemoteModule: ({ module, scope, runtime, publicPath, LoadingComponent, ErrorComponent, onError, componentProps, children, }: RemoteModuleOptions) => string | number | true | Iterable<React.ReactNode> | React.JSX.Element;
|
|
18
|
+
export declare const RemoteModule: <T extends object = any>({ module, scope, runtime, publicPath, LoadingComponent, ErrorComponent, onError, componentProps, children, }: RemoteModuleOptions<T>) => string | number | true | Iterable<React.ReactNode> | React.JSX.Element;
|
|
19
19
|
export {};
|
|
@@ -6,7 +6,9 @@ export function initGlobalStore(options) {
|
|
|
6
6
|
};
|
|
7
7
|
}
|
|
8
8
|
const store = window.__MF_GLOBAL_STORE__;
|
|
9
|
-
|
|
9
|
+
// 获取或创建 hostInfo
|
|
10
|
+
const existingHostInfo = store.hostRemotes.get(options.name);
|
|
11
|
+
const hostInfo = existingHostInfo || {
|
|
10
12
|
keys: new Set(),
|
|
11
13
|
nameKeyMap: new Map(),
|
|
12
14
|
conflictingModules: new Set()
|
|
@@ -23,10 +25,16 @@ export function initGlobalStore(options) {
|
|
|
23
25
|
hostName: options.name,
|
|
24
26
|
extraInfo: remote.extraInfo
|
|
25
27
|
};
|
|
28
|
+
// 如果已存在同名的 remote,先移除旧的信息
|
|
29
|
+
const existingKey = hostInfo.nameKeyMap.get(remote.name);
|
|
30
|
+
if (existingKey) {
|
|
31
|
+
hostInfo.keys.delete(existingKey);
|
|
32
|
+
store.remotes.delete(existingKey);
|
|
33
|
+
}
|
|
26
34
|
// 记录这个 host 使用的 remote key 和 name 到 key 的映射
|
|
27
35
|
hostInfo.keys.add(remoteKey);
|
|
28
36
|
hostInfo.nameKeyMap.set(remote.name, remoteKey);
|
|
29
|
-
//
|
|
37
|
+
// 检查是否与其他 host 的模块冲突
|
|
30
38
|
for (const [, info] of store.remotes.entries()){
|
|
31
39
|
if (info.name === remote.name && info.entry !== entry) {
|
|
32
40
|
console.warn(`[Module Federation] Remote module "${remote.name}" has multiple versions:`, `\nHost "${info.hostName}": ${info.entry}`, `\nHost "${options.name}": ${entry}`);
|
package/esm/RemoteModule.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
interface RemoteModuleOptions {
|
|
2
|
+
interface RemoteModuleOptions<T = any> {
|
|
3
3
|
module: string;
|
|
4
4
|
scope: string;
|
|
5
5
|
runtime?: {
|
|
@@ -12,8 +12,8 @@ interface RemoteModuleOptions {
|
|
|
12
12
|
onError?: (error: Error, info: {
|
|
13
13
|
componentStack: string;
|
|
14
14
|
}) => void;
|
|
15
|
-
componentProps?:
|
|
15
|
+
componentProps?: T;
|
|
16
16
|
children?: React.ReactNode;
|
|
17
17
|
}
|
|
18
|
-
export declare const RemoteModule: ({ module, scope, runtime, publicPath, LoadingComponent, ErrorComponent, onError, componentProps, children, }: RemoteModuleOptions) => string | number | true | Iterable<React.ReactNode> | React.JSX.Element;
|
|
18
|
+
export declare const RemoteModule: <T extends object = any>({ module, scope, runtime, publicPath, LoadingComponent, ErrorComponent, onError, componentProps, children, }: RemoteModuleOptions<T>) => string | number | true | Iterable<React.ReactNode> | React.JSX.Element;
|
|
19
19
|
export {};
|
package/esm/mf-global-store.js
CHANGED
|
@@ -7,7 +7,9 @@ export function initGlobalStore(options) {
|
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
9
|
var store = window.__MF_GLOBAL_STORE__;
|
|
10
|
-
|
|
10
|
+
// 获取或创建 hostInfo
|
|
11
|
+
var existingHostInfo = store.hostRemotes.get(options.name);
|
|
12
|
+
var hostInfo = existingHostInfo || {
|
|
11
13
|
keys: new Set(),
|
|
12
14
|
nameKeyMap: new Map(),
|
|
13
15
|
conflictingModules: new Set()
|
|
@@ -24,12 +26,18 @@ export function initGlobalStore(options) {
|
|
|
24
26
|
hostName: options.name,
|
|
25
27
|
extraInfo: remote.extraInfo
|
|
26
28
|
};
|
|
29
|
+
// 如果已存在同名的 remote,先移除旧的信息
|
|
30
|
+
var existingKey = hostInfo.nameKeyMap.get(remote.name);
|
|
31
|
+
if (existingKey) {
|
|
32
|
+
hostInfo.keys.delete(existingKey);
|
|
33
|
+
store.remotes.delete(existingKey);
|
|
34
|
+
}
|
|
27
35
|
// 记录这个 host 使用的 remote key 和 name 到 key 的映射
|
|
28
36
|
hostInfo.keys.add(remoteKey);
|
|
29
37
|
hostInfo.nameKeyMap.set(remote.name, remoteKey);
|
|
30
38
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
31
39
|
try {
|
|
32
|
-
//
|
|
40
|
+
// 检查是否与其他 host 的模块冲突
|
|
33
41
|
for(var _iterator = store.remotes.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
34
42
|
var _step_value = _sliced_to_array(_step.value, 2), info = _step_value[1];
|
|
35
43
|
if (info.name === remote.name && info.entry !== entry) {
|