web-extend-plugin-vue2 0.3.0 → 0.3.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
@@ -1,82 +1,77 @@
1
1
  # web-extend-plugin-vue2
2
2
 
3
- 面向 **Vue 2.6+** **Vue Router 3** Web 插件运行时:浏览器中拉取**插件清单**、加载入口脚本、执行 `activator(hostApi)`,并提供 **`ExtensionPoint`**、动态路由注册与受控 **`getBridge()`**;侧栏菜单由宿主根据路由 **`meta`** 自行推导(`buildMenuDescriptorsFromRoutes`)。发布物为预构建的 **`dist/`**(CJS/ESM),类型见根目录 **`index.d.ts`**。
3
+ Vue 2 host runtime for web plugin bootstrap, route registration, host API injection, and extension points.
4
4
 
5
- **Peer:`vue` ^2.6.14 \<3,`vue-router` ^3.5 \<4**(依赖 `router.addRoute`)。**
5
+ ## Install
6
6
 
7
- ### 本包 `devDependencies` 里的 `vue` / `vue-router` 会不会和宿主冲突?
7
+ ```bash
8
+ npm i web-extend-plugin-vue2
9
+ ```
8
10
 
9
- **不会误入发布物。** 二者在 **`peerDependencies`** 中声明,由**宿主工程安装并解析版本**;本仓库的 **`devDependencies`** 仅用于在本项目内跑 **TypeScript 检查、Vitest、 contributors 本地开发**。打包时 Rollup 将 `peerDependencies` 全部标为 **external**,**不会**把 Vue / Vue Router 打进 `dist/`,运行时使用的仍是宿主 `node_modules` 里那一份。
11
+ Peer dependencies:
10
12
 
11
- 若仍有顾虑,可这样理解:
13
+ - `vue >= 2.6.0 < 3`
14
+ - `vue-router >= 3.5.0 < 4`
12
15
 
13
- | 场景 | 说明 |
14
- |------|------|
15
- | **宿主正常 npm/yarn/pnpm 安装** | 安装器会按 peer 范围校验/提升,与单一 Vue 实例一致 |
16
- | **Monorepo / `npm link` / workspace** | 确保工作区根只解析出 **一个** `vue`(避免「双 Vue」);可用包管理器的 `overrides` / `resolutions` 钉版本 |
17
- | **版本下限** | 本库源码按 peer 下限(Vue 2.6+、Router 3.5+)编写;dev 使用较新 2.7 / 3.6 仅便于类型与本地调试,**不要求**宿主与 dev 完全一致,只要在 peer 范围内即可 |
16
+ ## Public API
18
17
 
19
- **本地验证 peer 下限**:在本包目录执行 **`npm run test:peer-min`**(临时将 `node_modules` 中的 `vue` / `vue-router` 换为与 `peerMinimumVersions` 一致的版本并执行 build+test,最后 `npm install` 恢复)。仓库已含 **GitHub Actions**(`.github/workflows/WEB_EXTEND_PLUGIN_VUE2.yml`)对 default / min 双矩阵跑 CI。
18
+ The package now exposes named exports only.
20
19
 
21
- ---
20
+ Core runtime:
22
21
 
23
- ## 如何使用
22
+ - `installWebExtendPluginVue2`
23
+ - `bootstrapPlugins`
24
+ - `resolveRuntimeOptions`
25
+ - `ensurePluginHostRoute`
26
+ - `createHostApi`
27
+ - `disposeWebPlugin`
28
+ - `getActivatedPluginIds`
29
+ - `getRegisteredTopRouteNamesForPlugin`
30
+ - `getContributedRoutesForPlugin`
24
31
 
25
- **一键接入**(注册全局 `ExtensionPoint` 并异步拉清单):
32
+ Utilities:
26
33
 
27
- ```js
28
- import { installWebExtendPluginVue2 } from 'web-extend-plugin-vue2'
34
+ - `createRequestBridge`
35
+ - `createVueCliAxiosInstallOptions`
36
+ - `composeManifestFetch`
37
+ - `manifestFetchCacheMiddleware`
38
+ - `wrapManifestFetchWithCache`
39
+ - `setWebExtendPluginEnv`
29
40
 
30
- installWebExtendPluginVue2(Vue, router, {
31
- manifestBase: '/fp-api', // 或与网关一致的前缀
32
- env: import.meta.env // Vite:可选,便于读取 VITE_*
33
- }).catch(console.warn)
34
- ```
41
+ Constants:
35
42
 
36
- **Vue CLI + 已有 axios `request`**(清单可走 Java,开发态可自动回退 `public/web-plugins/plugins.manifest.json`;**不再**默认注册 `/plugin` 壳,需显式 `ensurePluginHostRoute: true` 且配置 `pluginRoutesParentName` + `hostLayoutComponent`):
43
+ - `HOST_PLUGIN_API_VERSION`
44
+ - `RUNTIME_CONSOLE_LABEL`
45
+ - `defaultWebExtendPluginRuntime`
46
+ - `defaultManifestFetchCache`
47
+ - `defaultManifestMode`
48
+ - `routeSynthNamePrefix`
49
+ - `peerMinimumVersions`
50
+ - `webExtendPluginEnvKeys`
37
51
 
38
- **更少样板(推荐)**:自动写入 `window.Vue`(IIFE 插件与 build-kit 约定)、合并 `hostContext`(`router` + 可选 `store`)、默认 `manifestListPath` 为 **`/frontend-plugins`**(与 `VUE_APP_BASE_API` 拼接;若后端为 `/api/frontend-plugins` 请在第 4 参数传 `manifestListPath: '/api/frontend-plugins'`)、`isDev` 与构建环境一致。按需关闭全局 Vue:`{ exposeGlobalVue: false }`。
39
-
40
- ```js
41
- import { installVueCliAxiosWebPlugins } from 'web-extend-plugin-vue2'
42
- import request from '@/utils/request'
43
- import Layout from '@/layout'
44
- import store from '@/store'
52
+ Components:
45
53
 
46
- installVueCliAxiosWebPlugins(
47
- Vue,
48
- router,
49
- {
50
- request,
51
- hostLayoutComponent: Layout,
52
- store
53
- },
54
- {
55
- manifestBase: process.env.VUE_APP_BASE_API,
56
- pluginRoutesParentName: '__wepPluginHost',
57
- ensurePluginHostRoute: true
58
- }
59
- ).catch((e) => console.warn('[web-plugin] bootstrap failed', e))
60
- ```
54
+ - `ExtensionPoint`
61
55
 
62
- 等价于自行组合 `createVueCliAxiosQuickInstallOptions` + `installWebExtendPluginVue2`;仅选项、不要一键安装时:
56
+ ## Quick start
63
57
 
64
58
  ```js
65
- import { installWebExtendPluginVue2, createVueCliAxiosQuickInstallOptions } from 'web-extend-plugin-vue2'
59
+ import { installWebExtendPluginVue2, setWebExtendPluginEnv } from 'web-extend-plugin-vue2'
66
60
 
67
- installWebExtendPluginVue2(
68
- Vue,
69
- router,
70
- createVueCliAxiosQuickInstallOptions(router, { request, hostLayoutComponent: Layout, store }, { manifestBase: process.env.VUE_APP_BASE_API })
71
- ).catch(console.warn)
61
+ setWebExtendPluginEnv(import.meta.env)
62
+
63
+ installWebExtendPluginVue2(Vue, router, {
64
+ manifestBase: '/fp-api'
65
+ }).catch(console.warn)
72
66
  ```
73
67
 
74
- **显式逐字段**(与旧版一致,清单路径默认来自 `defaultWebExtendPluginRuntime` / 环境变量):
68
+ ## Vue CLI + axios
75
69
 
76
70
  ```js
77
71
  import { installWebExtendPluginVue2, createVueCliAxiosInstallOptions } from 'web-extend-plugin-vue2'
78
72
  import request from '@/utils/request'
79
73
  import Layout from '@/layout'
74
+ import store from '@/store'
80
75
 
81
76
  installWebExtendPluginVue2(
82
77
  Vue,
@@ -84,157 +79,35 @@ installWebExtendPluginVue2(
84
79
  createVueCliAxiosInstallOptions(
85
80
  { request },
86
81
  {
82
+ manifestBase: process.env.VUE_APP_BASE_API,
83
+ manifestListPath: '/frontend-plugins',
87
84
  hostLayoutComponent: Layout,
88
- pluginRoutesParentName: '__wepPluginHost',
89
- ensurePluginHostRoute: true
85
+ hostContext: { router, store },
86
+ ensurePluginHostRoute: true,
87
+ pluginRoutesParentName: 'pluginHost'
90
88
  }
91
89
  )
92
90
  ).catch(console.warn)
93
91
  ```
94
92
 
95
- 若启用壳路由:`pluginRoutesParentName`(如 **`__wepPluginHost`**)+ `pluginMountPath`(默认 **`/plugin`**)+ `ensurePluginHostRoute: true`。未启用壳时,`registerRoutes` 的 `path` 为**绝对路径**或宿主在 `transformRoutes` 中自行加前缀。
96
-
97
- **静态清单模式**(无需 Java `frontend-plugins`,将聚合 JSON 放入宿主 `public` 等静态目录):
98
-
99
- ```js
100
- installWebExtendPluginVue2(
101
- Vue,
102
- router,
103
- createVueCliAxiosInstallOptions({ request }, {
104
- manifestMode: 'static',
105
- staticManifestUrl: '/web-plugins/plugins.manifest.json'
106
- })
107
- ).catch(console.warn)
108
- ```
109
-
110
- JSON 体与 Java 清单接口一致(含 `hostPluginApiVersion`、`plugins[].id` / `entryUrl` 等),参见设计文档或示例 `plugins.manifest.json`。
111
-
112
- ### 开发态开箱即用(默认 API + 静态回退)
113
-
114
- 保持 **`manifestMode` 默认 `api`**、宿主仍只写 `createVueCliAxiosInstallOptions({ request }, { manifestBase, manifestListPath, ... })` 即可。当 **`isDev === true`** 时,若后端清单**请求失败**或 **`plugins` 为空**,框架会**自动**再拉取 **`devFallbackStaticManifestUrl`**(默认 **`/web-plugins/plugins.manifest.json`**)。把该文件放在宿主 **`public/web-plugins/`** 下即可与「不打后端 / 后端无插件」场景联调,无需在业务里切换 `manifestMode`。
115
-
116
- 插件源码热更新:配置 **`PLUGIN_WEB_PLUGIN_DEV_ORIGIN`**(Vue CLI 推荐 `PLUGIN_*` 进 `process.env`)与 **`PLUGIN_WEB_PLUGIN_DEV_IDS`**(或与 **`VITE_*`** 等价键),与原先隐式 dev 映射行为一致。关闭回退:`devManifestFallback: false` 或环境变量 **`VITE_WEB_PLUGIN_DEV_MANIFEST_FALLBACK=0`**。
117
-
118
- **按需组合**(自行注册 `ExtensionPoint`、控制引导时机):
119
-
120
- ```js
121
- import {
122
- bootstrapPlugins,
123
- createHostApi,
124
- resolveRuntimeOptions,
125
- ExtensionPoint
126
- } from 'web-extend-plugin-vue2'
127
-
128
- Vue.component('ExtensionPoint', ExtensionPoint)
129
- const runtime = resolveRuntimeOptions({ manifestBase: '/fp-api' })
130
- bootstrapPlugins(router, (id, r, kit) => createHostApi(id, r, kit), runtime).catch(console.warn)
131
- ```
132
-
133
- 清单请求地址:**`manifestBase` + `manifestListPath`**(默认路径段为 `/api/frontend-plugins`)。工厂请使用 **`(id, r, kit) => createHostApi(id, r, kit)`**,以便 `bridgeAllowedPathPrefixes` 等传入 `hostApi`。
134
-
135
- ---
136
-
137
- ## 主要配置(`resolveRuntimeOptions` / `install` 同源字段)
138
-
139
- | 字段 | 作用 |
140
- |------|------|
141
- | `manifestBase` | 清单服务 URL 前缀(无尾 `/`),默认 `/fp-api` |
142
- | `manifestListPath` | 清单路径段(以 `/` 开头),拼在 `manifestBase` 后 |
143
- | `manifestMode` | 默认 `api`;设为 `static` 时从 `staticManifestUrl` 用浏览器 `fetch` 拉取聚合 JSON(不经后端 list)。环境变量:`VITE_WEB_PLUGIN_MANIFEST_MODE` / `PLUGIN_WEB_PLUGIN_MANIFEST_MODE` |
144
- | `staticManifestUrl` | 静态聚合清单地址,如 `/web-plugins/plugins.manifest.json`。环境变量:`VITE_WEB_PLUGIN_STATIC_MANIFEST_URL` / `PLUGIN_WEB_PLUGIN_STATIC_MANIFEST_URL` |
145
- | `devManifestFallback` | 开发态 API 失败或空列表时是否回退静态 JSON(`manifestMode=api` 时默认开启)。`VITE_WEB_PLUGIN_DEV_MANIFEST_FALLBACK` |
146
- | `devFallbackStaticManifestUrl` | 回退地址,默认 `/web-plugins/plugins.manifest.json`。`VITE_WEB_PLUGIN_DEV_FALLBACK_MANIFEST_URL` |
147
- | `manifestFetchCredentials` | 拉清单时 `fetch` 的 `credentials`,默认 `include` |
148
- | `fetchManifest` | 自定义清单请求 `(ctx) => Promise<{ ok, data?, error? }>` |
149
- | `bridgeAllowedPathPrefixes` | `hostApi.getBridge().request(path)` 允许的 path 前缀 |
150
- | `allowedScriptHosts` | 允许加载插件脚本的主机名白名单 |
151
- | `isDev` / `webPluginDevOrigin` 等 | 开发态隐式 dev 入口与 SSE,见类型定义 |
152
- | `hostLayoutComponent` | 与 `ensurePluginHostRoute: true` 且配置了 `pluginRoutesParentName` 时用于自动注册壳路由的 Layout 组件 |
153
- | `pluginMountPath` / `pluginHostRouteMeta` / `ensurePluginHostRoute` | 壳路径(默认 `/plugin`)、壳 meta、**仅在为 true 时**自动注册壳(默认 **false**) |
154
- | `pluginRoutesParentName` | 命名父路由的 **name**;非空时 `registerRoutes` 子项通过 `addRoute(parentName, child)` 挂载 |
155
- | `adaptRouteDeclarations` / `transformRoutes` / `interceptRegisterRoutes` | 路由 PRD 适配与宿主扩展流水线 |
156
- | `buildMenuDescriptorsFromRoutes`(具名导出 / `WebExtendPluginVue2.host`) | 由插件提交的 `RouteConfig` 树与 **`meta.title` / `meta.menuTitle`** 等推导菜单数据,供宿主写入 Vuex 等 |
157
- | `hostContext` | **依赖注入(推荐)**:普通对象,引导时做**浅拷贝并浅冻结**后挂到 **`hostApi.hostContext`**,插件只读使用 `store` / `router` / 宿主开放 API 等,不污染 `HostApi` 顶层方法名 |
158
- | `onBeforePluginActivate` / `onAfterPluginActivate` / `onPluginActivateError` | **生命周期**:激活前(可 `throw` 跳过该插件)、成功后、抛错后;便于埋点、门禁、监控,各宿主同一套签名即可接入 |
159
-
160
- 环境:Vite 可在入口调用 **`setWebExtendPluginEnv(import.meta.env)`**,或在 options 里传 **`env`**。键名支持 **`VITE_*`** 与等价 **`PLUGIN_*`**(实现内会解析)。
161
-
162
- ### 宿主接入约定(跨项目统一)
163
-
164
- 1. **菜单**:插件在 `registerRoutes` 的 **`meta`** 中写明 `title` / `order` / `icon` / `permission` / `hidden` 等;宿主在 `onAfterPluginActivate` 或统一收集阶段用 **`buildMenuDescriptorsFromRoutes(routes, pluginId)`** 生成侧栏数据(或由宿主在 `transformRoutes` 之后自行扫 `router.getRoutes()`)。**不再**使用 `registerMenuItems`。
165
- 2. **宿主能力**:通过 **`hostContext`** 注入(如 `{ store, router, getDict }`),插件内使用 **`hostApi.hostContext.store`**,避免 `Vue.prototype` 魔法与命名冲突。
166
- 3. **拦截激活**:在 **`onBeforePluginActivate`** 中做权限/租户校验,不通过则 **`throw`**;错误用 **`onPluginActivateError`** 上报,勿在 error 钩子里再抛异常。
167
- 4. **卸载**:`disposeWebPlugin(pluginId)` 会 **`removeRoute`** 移除该插件登记的动态路由,并清理槽位、脚本与 teardown;侧栏需按 **`pluginId`** 或重建菜单树与路由对齐。
168
-
169
- ---
170
-
171
- ## 功能示例)
172
-
173
- **布局里开槽**(插件通过 `hostApi.registerSlotComponents('your.point.id', [...])` 注入组件):
174
-
175
- ```vue
176
- <ExtensionPoint point-id="app.toolbar.demo" />
177
- ```
178
-
179
- **侧栏菜单**(`registries` 仅含扩展点 `slots`;菜单与路由同源):
180
-
181
- ```js
182
- import { buildMenuDescriptorsFromRoutes } from 'web-extend-plugin-vue2'
183
-
184
- // 插件 activator 内:
185
- hostApi.registerRoutes([
186
- {
187
- path: 'hello',
188
- component: Hello,
189
- meta: { title: '插件 Hello', order: 10, pluginId: 'com.example' }
190
- }
191
- ])
192
-
193
- // 宿主在 onAfterPluginActivate 或自行约定的收集点:
194
- const items = buildMenuDescriptorsFromRoutes(
195
- [
196
- /* 与插件注册前相同的 RouteConfig 快照,或由宿主在 transformRoutes 中缓存 */
197
- ],
198
- pluginId
199
- )
200
- ```
201
-
202
- `disposeWebPlugin` 会移除对应动态路由;宿主从 state 中删除同一 `pluginId` 的菜单项即可。
203
-
204
- **宿主上下文(插件读宿主能力)**:
205
-
206
- ```js
207
- // install / resolveRuntimeOptions
208
- hostContext: {
209
- store,
210
- router,
211
- // 仅暴露你愿意让插件调用的键;勿放入密钥
212
- }
213
- // 插件 activator 内:hostApi.hostContext.store / .router
214
- ```
215
-
216
- **路由扩展(宿主)**:在 `resolveRuntimeOptions` 里提供 `transformRoutes` 或 `adaptRouteDeclarations`,插件在 `activator` 第二个参数中取冻结的 **`pluginRecord`**(可含清单里的 `routeDeclarations`)。
217
-
218
- **卸载插件**(含 `router.removeRoute` 批量撤销该插件登记的顶层路由名):
219
-
220
- ```js
221
- import { disposeWebPlugin } from 'web-extend-plugin-vue2'
222
- disposeWebPlugin('com.your.plugin.id')
223
- ```
224
-
225
- ---
226
-
227
- ## API 浏览
228
-
229
- - **具名导出**:与下述命名空间指向同一实现,便于 tree-shaking。
230
- - **`WebExtendPluginVue2`**:`install`、`runtime`(含 `bootstrapPlugins`、`resolveRuntimeOptions`、`wrapManifestFetchWithCache` 等)、`host`、`config`、`constants`、`components`、`presets`(`vueCliAxios`,含 `createQuickInstallOptions`、`defaultJavaManifestListPath`)。另导出 **`installVueCliAxiosWebPlugins`**(一键安装)。
231
-
232
- 更细的签名与说明以 **`index.d.ts`** 为准。
233
-
234
- **默认运行时常量与环境键名**统一在源码 **`src/core/public-config-defaults.ts`**(打包后通过 `defaultWebExtendPluginRuntime`、`webExtendPluginEnvKeys`、`WebExtendPluginVue2.config` 暴露),修改默认值或对照 `VITE_*` 时请只改该文件。
235
-
236
- ---
237
-
238
- ## 仓库
239
-
240
- <https://github.com/xtemplus/extend-plugin-framework/tree/master/web-extend-plugin-vue2> · Apache-2.0
93
+ ## Important runtime options
94
+
95
+ - `manifestBase`: API prefix, default `/fp-api`
96
+ - `manifestListPath`: manifest path segment, default `/api/frontend-plugins`
97
+ - `manifestMode`: `api` or `static`
98
+ - `staticManifestUrl`: required when `manifestMode` is `static`
99
+ - `devManifestFallback`: whether dev mode falls back to a static manifest
100
+ - `devFallbackStaticManifestUrl`: default `/web-plugins/plugins.manifest.json`
101
+ - `allowedScriptHosts`: allowed remote script hosts
102
+ - `bridgeAllowedPathPrefixes`: allowed bridge request path prefixes
103
+ - `hostLayoutComponent`: layout component for plugin shell route
104
+ - `pluginMountPath`: shell mount path, default `/plugin`
105
+ - `pluginRoutesParentName`: explicit parent route name for child plugin routes
106
+ - `ensurePluginHostRoute`: when `true`, auto-registers the shell route
107
+ - `hostContext`: readonly host dependencies injected into `hostApi.hostContext`
108
+
109
+ ## Notes
110
+
111
+ - `pluginRoutesParentName` has no implicit default. Pass it explicitly when you want child routes mounted under a named parent route.
112
+ - `installWebExtendPluginVue2` no longer accepts install-only wrapper options. Runtime environment injection should use `setWebExtendPluginEnv(...)`.
113
+ - Vue CLI preset helpers were reduced to a single builder: `createVueCliAxiosInstallOptions`.