远程小部件
远程小部件(Remote Vue)
插件可以把一个 .vue 单文件组件"投"到基座工作台/看板等位置渲染,而无需把组件编译进基座。基座与脚手架都内置了 远程 Vue 加载器(基于 vue3-sfc-loader):运行时拉取远程 .vue 源码,在浏览器里即时编译成组件挂载。
怎么用
用一个 AmRemoteVue 组件(或 useRemoteVue hook)传入远程组件地址/元信息:
<template>
<!-- 直接给 URL -->
<AmRemoteVue url="/app/am_demo/widget/AppWidget.vue" name="am_demo_widget" />
<!-- 或给元信息(带缓存/版本控制) -->
<AmRemoteVue :meta="{ plugin: 'am_demo', name: 'app_widget', url: '/app/am_demo/widget/AppWidget.vue', version: '1.0.0' }" />
</template>AmRemoteVue 处理三种状态:加载中(v-loading)、失败(ElAlert + 重试按钮)、空(ElEmpty),并向远程组件透传 componentProps 与 componentMeta、冒泡组件 message 事件。
组件元信息
interface RemoteVueComponentMeta {
plugin?: string // 归属插件(缓存清理维度)
name: string
url: string // 远程 .vue 源地址
version?: string
hash?: string // 内容指纹,优先用于缓存键与失效
cache_ttl?: number // 缓存存活毫秒
preload?: boolean // 是否预热
props?: Record<string, any>
// type/entry/title/description 供工作台展示
}组件里能用哪些依赖
远程组件在基座进程内编译执行,共享一份 moduleCache:
vue、element-plus、@element-plus/icons-vue复用宿主实例(不会重复打包、样式/状态与宿主一致);@am/request:加载器注入的请求模块,组件内import它即可发带登录态的请求。
远程组件的 <script> 里 import 这些模块会被解析到宿主已提供的实例。
安全边界
URL 白名单
加载前经 assertAllowedRemoteVueUrl 校验,不合规直接抛错:
- 拒绝
javascript:/data:/blob:/file:等危险协议,只允许http/https; - 生产环境拒绝非本地
http:(明文)远程源(allowDevHttp仅 dev); - 域名白名单:仅同域、API 前缀 origin、代理 origin;
- 路径前缀白名单:默认只允许
/app/(即插件静态资源目录)与 API 前缀路径。
因此远程组件源码应放在插件 public/ 下、以 /app/{name}/... 对外暴露(如 am-serve/plugin/am_demo/public/widget/AppWidget.vue → /app/am_demo/widget/AppWidget.vue)。
缓存
两层缓存,键含 plugin:name:version/hash:
- 源缓存:远程
.vue文本,默认 TTL 5 分钟; - 组件缓存:编译后的组件对象;命中直接复用,
force(重试/强制刷新)时失效重取。
带 version 或 hash 时用于生成稳定缓存键,发新版即失效;按插件卸载可 clearByPlugin(plugin) 清干净。请求带 credentials: 'include'(同域带 cookie),并支持 AbortSignal 取消(组件卸载/源码变更时中断旧请求)。
小部件元数据落库
小部件的展示清单/可见范围由后台与数据库管理(与菜单、配置同路),不写进 manifest.json。插件侧只需把 .vue 落到静态目录、按上面的 meta.url 引用即可。
