@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 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={{
@@ -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?: any;
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
- const hostInfo = {
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}`);
@@ -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?: any;
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 {};
@@ -7,7 +7,9 @@ export function initGlobalStore(options) {
7
7
  };
8
8
  }
9
9
  var store = window.__MF_GLOBAL_STORE__;
10
- var hostInfo = {
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ice/mf-runtime",
3
- "version": "0.0.4",
3
+ "version": "0.0.6-beta.1",
4
4
  "description": "ice mf runtime",
5
5
  "files": [
6
6
  "esm",