@hhfenpm/micro-app 1.0.3 → 1.0.5

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
@@ -1,6 +1,6 @@
1
1
  # @hhfenpm/micro-app
2
2
 
3
- 微前端通信桥接和状态同步工具,支持父子应用之间的通信、状态同步和生命周期管理。
3
+ 基于 iframe + postMessage 的微前端工具:父子应用**通信桥接**、**Vuex 状态同步**、**生命周期**与**路由同步**。
4
4
 
5
5
  ## 安装
6
6
 
@@ -10,202 +10,200 @@ npm install @hhfenpm/micro-app
10
10
  yarn add @hhfenpm/micro-app
11
11
  ```
12
12
 
13
- ## 功能特性
13
+ ## 能力概览
14
14
 
15
- - 🔗 **通信桥接**:支持父子应用之间的方法调用和通信
16
- - 🔄 **状态同步**:自动同步 Vuex store 状态
17
- - 🎯 **生命周期管理**:支持微前端生命周期(mount、update、unmount)
18
- - 🛣️ **路由同步**:自动同步子应用路由到父应用
19
- - ⚙️ **可配置**:支持自定义处理器、状态映射等
15
+ | 能力 | 说明 |
16
+ |------|------|
17
+ | **通信桥接** | 子应用通过 `vm.$base.命名空间.方法(params)` 调用父应用方法,支持 Promise |
18
+ | **状态同步** | 父子应用 Vuex `base` 模块双向同步 |
19
+ | **生命周期** | 父应用调用 `mount/update/unmount`,子应用通过 `window.__MICRO_APP_LIFECYCLE__` 响应 |
20
+ | **路由同步** | 子应用路由变化同步到父应用 URL(需子应用调用 `store.attachRouterSync(router)`) |
20
21
 
21
- ## 使用方式
22
+ ---
22
23
 
23
- ### 1. 初始化通信桥接
24
+ ## 一、Bridge(通信桥接)
24
25
 
25
- #### 父应用
26
+ ### 父应用
27
+
28
+ 父应用需提供 `handlers`:`{ 命名空间: { 方法名: 函数 } }`。可使用内置 `createRegisterHandlers` 生成 `ui`(Element UI 等)和 `cs`(Electron)两个命名空间:
26
29
 
27
30
  ```javascript
28
- import { initBridge } from '@hhfenpm/micro-app'
29
- import Vue from 'vue'
31
+ import { initBridge, createRegisterHandlers } from '@hhfenpm/micro-app'
30
32
 
31
33
  const vm = new Vue({ /* ... */ })
32
34
 
33
- // 创建处理器(项目特定)
34
- const handlers = {
35
- elementUI: {
36
- $message: (...args) => vm.$message(...args),
37
- // ... 其他 Element UI 方法
38
- },
39
- electron: {
40
- // ... Electron 方法
41
- },
42
- }
35
+ // getElectron:返回 electron 模块,无则 () => ({}) 或 () => require('@/utils/electron')
36
+ const getElectron = () => ({}) // 或 () => require('@/utils/electron')
37
+ const toHandlers = createRegisterHandlers(getElectron)
43
38
 
44
- // 初始化桥接
45
39
  initBridge({
46
40
  isParent: true,
47
41
  vm,
48
- handlers,
42
+ handlers: toHandlers(vm),
49
43
  iframeSelector: '#microApp', // 可选,默认 '#microApp'
50
44
  })
51
45
  ```
52
46
 
53
- #### 子应用
47
+ `createRegisterHandlers(getElectron)` 返回 `(vm) => ({ ui, cs })`:
48
+
49
+ - **ui**:`$message`、`$success`、`$warning`、`$error`、`$notify`、`$confirm`、`$alert`、`$prompt`、`$loading`
50
+ - **cs**:Electron 能力(由 `getElectron()` 提供,缺失的方法为 noop)
51
+
52
+ ### 子应用
54
53
 
55
54
  ```javascript
56
55
  import { initBridge } from '@hhfenpm/micro-app'
57
- import Vue from 'vue'
58
56
 
59
57
  const vm = new Vue({ /* ... */ })
60
58
 
61
- // 初始化桥接
62
- initBridge({
63
- isParent: false,
64
- vm,
65
- })
59
+ initBridge({ isParent: false, vm })
66
60
 
67
- // 使用 $base 调用父应用方法
68
- vm.$base.elementUI.$message('Hello from child app')
69
- vm.$base.electron.show()
61
+ // 调用父应用:vm.$base.命名空间.方法(params),返回 Promise
62
+ vm.$base.ui.$message('来自子应用')
63
+ vm.$base.ui.$confirm('确认?').then(ok => { /* ... */ })
64
+ vm.$base.cs.show()
70
65
  ```
71
66
 
72
- ### 2. 使用核心功能
67
+ ---
68
+
69
+ ## 二、Core(子应用 URL / 部署检测)
70
+
71
+ 根据「路径 → 模块名」映射、以及「启用模块列表」,计算当前路由是否命中某子应用、其入口 URL、是否已部署。
73
72
 
74
73
  ```javascript
75
74
  import { createMicroAppCore } from '@hhfenpm/micro-app'
76
75
 
77
- // 定义模块路由映射
78
- const ModelMap = () => ({
79
- 'module1': ['/module1', '/m1'],
80
- 'module2': ['/module2'],
76
+ const modelMap = () => ({
77
+ 'disease-analysis': ['/disease-analysis', '/ds-consult'],
78
+ 'health': ['/health-manage'],
81
79
  })
82
80
 
83
- // 创建核心功能实例
84
81
  const core = createMicroAppCore({
85
- modelMap: ModelMap,
86
- enabledModules: () => window.GLOBAL_CONFIG?.microApp || null,
82
+ modelMap,
83
+ enabledModules: () => window.GLOBAL_CONFIG?.microApp || null, // 可选,不传则用 GLOBAL_CONFIG.microApp
87
84
  })
88
85
 
89
- // 使用
90
- const module = core.microAppModule('/module1')
91
- const src = core.microAppSrc('/module1')
92
- const deployed = await core.microAppDeployed('module1')
86
+ // 根据路径得到模块名,未命中或未启用则为 null
87
+ const module = core.microAppModule('/disease-analysis') // 'disease-analysis'
88
+
89
+ // 子应用完整 URL(含 hash)
90
+ const src = core.microAppSrc('/disease-analysis')
91
+
92
+ // 是否已部署(HEAD /module 可访问)
93
+ const ok = await core.microAppDeployed('disease-analysis')
93
94
  ```
94
95
 
95
- ### 3. 使用状态同步插件
96
+ ---
97
+
98
+ ## 三、Store 插件(状态同步)
99
+
100
+ 在 Vuex 中注册 `baseSyncPlugin`,并在**子应用**中调用 `store.attachRouterSync(router)` 以同步路由。
101
+
102
+ ### 父应用
96
103
 
97
104
  ```javascript
98
105
  import Vuex from 'vuex'
99
106
  import { baseSyncPlugin } from '@hhfenpm/micro-app'
107
+ import base from './store/modules/base' // 需含 base/SYNC_STATE
108
+
109
+ const store = new Vuex.Store({
110
+ modules: { base },
111
+ plugins: [baseSyncPlugin({ isParent: true, iframeSelector: '#microApp' })],
112
+ })
113
+ ```
114
+
115
+ ### 子应用
116
+
117
+ ```javascript
118
+ import { baseSyncPlugin } from '@hhfenpm/micro-app'
119
+ import base from './store/modules/base'
100
120
 
101
- // 创建 Vuex Store
102
121
  const store = new Vuex.Store({
103
- modules: {
104
- base: {
105
- namespaced: true,
106
- state: {
107
- patient_id: null,
108
- },
109
- mutations: {
110
- SYNC_STATE(state, payload) {
111
- Object.assign(state, payload)
112
- },
113
- },
114
- },
115
- },
116
- plugins: [
117
- baseSyncPlugin({
118
- isParent: false, // 子应用设为 false
119
- iframeSelector: '#microApp',
120
- }),
121
- ],
122
+ modules: { base },
123
+ plugins: [baseSyncPlugin({ isParent: false, iframeSelector: '#microApp' })],
122
124
  })
123
125
 
124
- // 子应用附加路由同步
125
126
  import router from './router'
126
- store.attachRouterSync(router)
127
+ store.attachRouterSync(router) // 必调,用于把子应用路由同步到父应用
127
128
  ```
128
129
 
129
- ### 4. 生命周期管理
130
+ `base` 模块需提供 `base/SYNC_STATE` mutation,用于接收并合并同步过来的 state。
131
+
132
+ ---
130
133
 
131
- #### 子应用
134
+ ## 四、生命周期
135
+
136
+ ### 子应用
137
+
138
+ 在子应用入口注册:
132
139
 
133
140
  ```javascript
134
- // 注册生命周期钩子
135
141
  window.__MICRO_APP_LIFECYCLE__ = {
136
- mount(payload) {
137
- console.log('微前端已挂载', payload)
138
- },
139
- update(payload) {
140
- console.log('微前端已更新', payload)
141
- },
142
- unmount(payload) {
143
- console.log('微前端已卸载', payload)
144
- },
142
+ mount(payload) { /* 挂载后 */ },
143
+ update(payload) { /* 更新时,如路由变化 */ },
144
+ unmount(payload) { /* 卸载前 */ },
145
145
  }
146
146
  ```
147
147
 
148
- #### 父应用
148
+ ### 父应用
149
+
150
+ 由 `baseSyncPlugin` 在 store 上挂载 `callMicroAppLifeCycle`,在 iframe 加载完成、路由变化、子应用切换时调用:
149
151
 
150
152
  ```javascript
151
- // 调用生命周期
152
- store.callMicroAppLifeCycle('mount', { /* payload */ })
153
- store.callMicroAppLifeCycle('update', { /* payload */ })
154
- store.callMicroAppLifeCycle('unmount', { /* payload */ })
153
+ store.callMicroAppLifeCycle('mount', { route: '/xxx' })
154
+ store.callMicroAppLifeCycle('update', { route: '/yyy' })
155
+ store.callMicroAppLifeCycle('unmount')
155
156
  ```
156
157
 
157
- ## API 文档
158
-
159
- ### Bridge
158
+ ---
160
159
 
161
- #### `initBridge(options)`
160
+ ## API 一览
162
161
 
163
- 初始化通信桥接。
162
+ | 接口 | 说明 |
163
+ |------|------|
164
+ | `initBridge({ isParent, vm, iframeSelector?, handlers? })` | 初始化桥接;父应用传 `handlers`,子应用可访问 `vm.$base` |
165
+ | `createRegisterHandlers(getElectron?)` | 返回 `(vm) => ({ ui, cs })`,用作 `handlers` |
166
+ | `createMicroAppCore({ modelMap, enabledModules? })` | 返回 `{ microAppModule, microAppSrc, microAppDeployed }` |
167
+ | `baseSyncPlugin({ isParent, iframeSelector? })` | Vuex 插件,并挂载 `store.attachRouterSync`、`store.callMicroAppLifeCycle` |
164
168
 
165
- **参数:**
166
- - `options.isParent` (boolean): 是否为父应用
167
- - `options.vm` (Object): Vue 实例
168
- - `options.iframeSelector` (string): iframe 选择器,默认 `'#microApp'`
169
- - `options.handlers` (Object): 处理器对象(父应用需要)
169
+ ### 参数说明
170
170
 
171
- ### Core
171
+ - **initBridge**
172
+ - `isParent`: 是否父应用
173
+ - `vm`: Vue 实例(子应用会在其上挂 `vm.$base`、`vm.$baseReady`)
174
+ - `iframeSelector`: 父应用 iframe 选择器,默认 `'#microApp'`
175
+ - `handlers`: 仅父应用需要,`{ [namespace]: { [method]: (params)=>any } }`
172
176
 
173
- #### `createMicroAppCore(options)`
177
+ - **createRegisterHandlers**
178
+ - `getElectron`: `() => electronModule`,可选;异常或未传时 `cs` 使用 noop
174
179
 
175
- 创建微前端核心功能实例。
180
+ - **createMicroAppCore**
181
+ - `modelMap`: `() => ({ [moduleName]: path[] })`,必填
182
+ - `enabledModules`: `() => string[]` 或 `string[]`,可选;缺省时从 `window.GLOBAL_CONFIG.microApp` 读取
176
183
 
177
- **参数:**
178
- - `options.modelMap` (Function): 模块路由映射函数,返回 `{ [moduleName]: string[] }`
179
- - `options.enabledModules` (Array|Function): 启用的模块列表或获取模块列表的函数
184
+ - **baseSyncPlugin**
185
+ - `isParent`: 是否父应用
186
+ - `iframeSelector`: 默认 `'#microApp'`
180
187
 
181
- **返回:**
182
- - `microAppModule(path)`: 根据路径获取模块名
183
- - `microAppSrc(path)`: 生成完整 URL
184
- - `microAppDeployed(module)`: 检测模块是否已部署
188
+ ---
185
189
 
186
- ### Store
187
-
188
- #### `baseSyncPlugin(options)`
189
-
190
- 创建状态同步插件。
190
+ ## 注意事项
191
191
 
192
- **参数:**
193
- - `options.isParent` (boolean): 是否为父应用
194
- - `options.iframeSelector` (string): iframe 选择器
192
+ 1. **同源**:postMessage 仅在同源下使用,需校验 `event.origin`。
193
+ 2. **base 模块**:`baseSyncPlugin` 通过 `base/SYNC_STATE` 同步;`base` 的 state 结构需与约定一致。
194
+ 3. **子应用必调**:`store.attachRouterSync(router)`,否则子应用路由不会回写到父应用 URL。
195
+ 4. **Proxy**:`vm.$base` 依赖 Proxy,不支持 IE11。
195
196
 
196
- ## 浏览器兼容性
197
+ ---
197
198
 
198
- - 现代浏览器(Chrome, Firefox, Safari, Edge)
199
- - 需要支持 `postMessage` API
200
- - 需要支持 `Proxy` API(IE 11 不支持)
199
+ ## 兼容性
201
200
 
202
- ## 注意事项
201
+ - 现代浏览器(Chrome、Firefox、Safari、Edge)
202
+ - 依赖 `postMessage`、`Proxy`
203
+ - Vue 2.6+ / 3.x,Vuex 3.x / 4.x(peerDependencies)
203
204
 
204
- 1. **安全性**:消息通信会检查 `origin`,确保只在同源窗口间通信
205
- 2. **状态同步**:状态同步使用深拷贝,避免引用污染
206
- 3. **生命周期**:子应用需要注册 `window.__MICRO_APP_LIFECYCLE__` 对象
207
- 4. **路由同步**:子应用需要调用 `store.attachRouterSync(router)` 附加路由同步
205
+ ---
208
206
 
209
- ## 许可证
207
+ ## 许可
210
208
 
211
209
  MIT
package/dist/index.esm.js CHANGED
@@ -1,12 +1,24 @@
1
1
  var uiHandler = vm => ({
2
- $message: vm.$message,
2
+ $message: (...args) => vm.$message(...args),
3
3
  $success: msg => vm.$message.success(msg),
4
4
  $warning: msg => vm.$message.warning(msg),
5
5
  $error: msg => vm.$message.error(msg),
6
6
  $notify: options => vm.$notify(options),
7
- $confirm: (...args) => vm.$confirm(...args).then(() => true).catch(() => false),
8
- $alert: (...args) => vm.$alert(...args).then(() => true).catch(() => false),
9
- $prompt: (...args) => vm.$prompt(...args).then(res => res.value).catch(() => null),
7
+ $confirm: (...args) =>
8
+ vm
9
+ .$confirm(...args)
10
+ .then(() => true)
11
+ .catch(() => false),
12
+ $alert: (...args) =>
13
+ vm
14
+ .$alert(...args)
15
+ .then(() => true)
16
+ .catch(() => false),
17
+ $prompt: (...args) =>
18
+ vm
19
+ .$prompt(...args)
20
+ .then(res => res.value)
21
+ .catch(() => null),
10
22
  $loading: options => {
11
23
  const loading = vm.$loading(options);
12
24
  return () => loading.close()
package/dist/index.js CHANGED
@@ -3,14 +3,26 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var uiHandler = vm => ({
6
- $message: vm.$message,
6
+ $message: (...args) => vm.$message(...args),
7
7
  $success: msg => vm.$message.success(msg),
8
8
  $warning: msg => vm.$message.warning(msg),
9
9
  $error: msg => vm.$message.error(msg),
10
10
  $notify: options => vm.$notify(options),
11
- $confirm: (...args) => vm.$confirm(...args).then(() => true).catch(() => false),
12
- $alert: (...args) => vm.$alert(...args).then(() => true).catch(() => false),
13
- $prompt: (...args) => vm.$prompt(...args).then(res => res.value).catch(() => null),
11
+ $confirm: (...args) =>
12
+ vm
13
+ .$confirm(...args)
14
+ .then(() => true)
15
+ .catch(() => false),
16
+ $alert: (...args) =>
17
+ vm
18
+ .$alert(...args)
19
+ .then(() => true)
20
+ .catch(() => false),
21
+ $prompt: (...args) =>
22
+ vm
23
+ .$prompt(...args)
24
+ .then(res => res.value)
25
+ .catch(() => null),
14
26
  $loading: options => {
15
27
  const loading = vm.$loading(options);
16
28
  return () => loading.close()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hhfenpm/micro-app",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "微前端通信桥接和状态同步工具,支持父子应用通信、状态同步、生命周期管理",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",