@axewo/fin-micro

中文文档
3.0.15发布于 2026/11/05MITTypeScriptESM + CJS近 30 天下载 3011
中文使用文档
文档目录32 节
  1. 快速开始
  2. 第一步:创建基座和子应用
  3. 第二步:安装依赖并启动
  4. 第三步:配置业务入口与认证
  5. 第四步:检查、构建与部署
  6. 能力与配置参考
  7. 可配置业务区水印
  8. 标准公共外壳与自定义布局
  9. 配置与插槽的升级边界
  10. 已有项目接入
  11. 刷新启动占位
  12. 按需获取当前 Token
  13. 子应用生命周期与环境判断
  14. 创建命令与项目维护
  15. 基座多应用可信注册表
  16. 业务功能目录
  17. vue 独立布局与本地路由菜单
  18. host 本地登录与主页体验
  19. host 真实路由与 URL 所有权
  20. host 统一路由守卫与扩展
  21. 启动依赖门禁
  22. 公共配置、错误边界与登录失效
  23. 平台认证适配器与模板更新
  24. 认证模式、启动就绪与运行状态
  25. 公共工作区与运行时资源治理
  26. 离页守卫的等待上限
  27. 未保存表单
  28. 响应式权限示例
  29. locales / router / stores 接线
  30. 包入口
  31. 使用前必须知道
  32. 生产构建与接入检查

@axewo/fin-micro

在线文档

统一页签式微前端库:无框架 core/SDK、Wujie 应用运行时、Vue 页级缓存适配、浏览器恢复和独立 iframe RPC。

快速开始

本说明直接提供创建、运行、接入和部署步骤,无需访问其他文档。运行环境要求 Node.js 18 及以上,并安装与生成项目配置兼容的 pnpm。

第一步:创建基座和子应用

在同一个父目录下执行,目标目录必须不存在:

npx @axewo/fin-micro@latest create my-host --template host --layout standard
npx @axewo/fin-micro@latest create my-business --template vue --app-id business --port 7101 --layout standard

基座默认端口为 7100,默认登记的子应用标识为 business、入口为 http://localhost:7101。子应用标识与基座注册表必须一致。命令只生成文件,不自动安装依赖。

第二步:安装依赖并启动

分别在两个终端中执行:

# 终端一:启动基座
cd my-host
pnpm install
pnpm dev
# 终端二:启动子应用
cd my-business
pnpm install
pnpm dev

打开 http://localhost:7100,使用开发演示账号 demo、密码 123456 登录,应进入本地主页。此时不需要后端;子应用离线也不影响基座本地主页。

打开 http://localhost:7101 可以单独访问子应用。子应用默认需要真实认证接口,不会自动沿用基座的演示登录;要完成嵌入业务页面验收,还需完成下一步的认证配置。

第三步:配置业务入口与认证

  1. 基座在 src/configs/microApps.ts 维护子应用注册表;修改标识或端口时,同步修改注册项及对应环境配置。新增应用不能只增加环境变量。
  2. 基座真实认证在项目根目录 .env.local 设置 VITE_AUTH_DEMO=false,按 src/platform/ 中的适配实现对接会话、登录、菜单和退出接口。
  3. 子应用独立认证在 src/apis/auth.ts 对接实际接口;根目录 .env.local 的 VITE_MICRO_AUTH_MODE 可设为 auto、host 或 independent。
  4. 默认注册项 shareToken:false 不提供宿主凭据能力。只有确认子应用完全可信且需要共享认证时,才在基座注册表显式设为 true,并确保当前会话授予该应用权限。不能仅修改子应用认证模式来获取宿主凭据。
  5. 按生成项目的 .env.example 配置接口目录;VITE_API_BASE 与 VITE_API_TRUSTED_BASE 必须一致,且以 / 结尾。环境变量会进入前端产物,禁止写入密码或访问凭据。

基座认证返回 { user: { id, name }, permissions: string[], appIds: string[], accessToken?: string };菜单接口返回 { apps: [{ appId, menus }] },必须完整覆盖所有已授权应用。菜单叶子示例:

{
  "menuId": "records",
  "name": "业务列表",
  "target": {
    "tabId": "business:list",
    "route": "/list"
  }
}

验收:独立登录后能访问子应用列表;基座登录后能从菜单打开已授权子应用;未登录或未授权访问被拒绝。演示模式仅用于本地开发,生产构建不会启用演示身份,也不会在真实接口失败后回退演示。

第四步:检查、构建与部署

在基座和子应用目录中分别执行:

pnpm check:runtime
pnpm typecheck
pnpm build

将各项目生成的 dist 分别部署,并在构建前配置基座注册表中的正式子应用入口。非本机应用入口使用 HTTPS,不能保留本地开发地址。

基座服务器需把 /login、/home、/profile、/micro/ 下的业务深链等前端路由回退到基座入口页面;静态资源和接口请求不能回退为页面。子目录部署还需同步配置构建基础路径。开发服务器的接口代理不会随构建产物发布,生产环境必须自行配置接口网关、跨源策略与认证防护。

部署后检查:基座深链刷新、子应用独立访问、嵌入菜单导航、详情关闭返回、页签恢复、退出登录及无权限访问。升级依赖后需要重新构建和发布;已生成项目的源文件不会被自动覆盖。

能力与配置参考

以下内容说明运行库与生成项目的主要配置,按实际接入需求查阅。

可配置业务区水印

@axewo/fin-ui 导出 FinWatermark、WatermarkConfig、normalizeWatermarkConfig。host/vue 的 standard/custom 模板均接入,配置在生成项目 src/utils/watermarkConfig.ts:

export const watermarkConfig = reactive<WatermarkConfig>({
  enabled: true,
  text: ['内部资料', '自定义文字'],
  color: '#64748b',
  opacity: 0.12,
  rotate: -22,
  fontSize: 16,
  fontFamily: 'sans-serif',
  gap: [100, 80], // 水平/垂直间距,越小越密
})

当前为前端配置;后续由项目 apis/ 适配真实接口并 Object.assign(watermarkConfig, result),无需更换组件,也没有预设后端协议。不要把 Token 等凭据当水印内容。字号限制 10~64、角度 -180~180、间距 16~600、透明度 0~1,文字最多四行、每行 120 字。

水印只覆盖右侧稳定业务视口,业务长页滚动不带走水印,不覆盖头部、侧栏和页签;登录页不绘制。Vue 嵌入运行由基座统一绘制,独立运行才挂载自己的水印。自定义接入需将组件置于 position: relative 的非滚动视口内,与业务滚动容器作为兄弟节点;公共 StandaloneShell 提供 workspace-overlay 插槽。

组件使用 Canvas 平铺、pointer-events: none,观察自身属性和直接父容器的节点删除,并定时检查常见隐藏样式。合法配置更新、关闭和卸载均清理观察器和定时器。Canvas 不可用或绘制失败会触发 error 事件并告警,本轮不启动无限重试;应用可按合规要求自行决定是否阻断业务。

纯前端水印不能保证无法通过 JS、样式或开发者工具移除:祖先容器被隐藏、脚本停用、截图后处理等均不受此机制保障,自动恢复只能提高篡改成本,不能当安全边界。下载文件需要水印时应在服务端生成;更强溯源需配合服务端审计与权限控制。

标准公共外壳与自定义布局

宿主模板的业务地址统一使用 /micro/{appId}/{子应用内路径}?query,例如 /micro/business/detail?id=1001;基座本地页面仍使用 /home、/profile。/workspace 只表示无参数的工作区入口,不再解析旧 /workspace?tab=... 链接。嵌入子应用仍使用 memory history,独立运行仍使用自身 hash 路由。

地址不携带 tabId:模板在授权菜单中查回静态页签的原 ID,演示详情仍使用 ${appId}:detail:${id};真实业务需在 src/router/targets.ts 中实现与菜单及子应用导航一致的动态身份策略,并由 platform/access.ts 校验权限。完整业务路径与 query 仍交给子应用;query 按键排序,重复参数保留顺序。完全相同的 URL 对应一个业务页签,不能靠不同的随机 tabId 创建可区分的同地址副本。

该变更利用现有 connectMicroHostRouter 的 target/location 映射,不修改核心缓存或生命周期协议。已有项目需同步 router/index.ts、targets.ts、guards.ts、workspace.ts;只升级 npm 不会覆盖项目源文件。生产服务器须将 /micro/ 下的深链回退到基座 index.html,子应用静态资源另用独立目录。

CLI 支持 --layout standard|custom,省略时默认 standard;交互创建时也可选择。

npx @axewo/fin-micro@latest create my-host --template host --layout standard
npx @axewo/fin-micro@latest create my-business --template vue --layout custom
  • standard:生成项目从 @axewo/fin-micro/layout 导入 HostShell 或 StandaloneShell,并显式导入 @axewo/fin-micro/layout/style.css。默认头部、菜单、页签等展示由包维护,升级依赖并重新构建后获得未覆盖区域的公共修复。
  • custom:保留完整可运行的本地布局 SFC 与样式,功能基线一致;展示代码的后续变更需要项目自行合并,不会被 npm 升级覆盖。
  • 宿主侧栏菜单名称前展示图标:菜单 icon 使用 HomeFilled、Folder、List、User 等 Element Plus 图标标识;未配置或不在本地映射白名单中的名称会安全回退到文件/文件夹图标。后台只传标识字符串,不传组件代码、HTML 或远程图标 URL。独立 Vue 菜单使用路由 meta.icon 组件。
  • 两种模式的认证、授权、Token、唯一 host/runtime、路由连接、页签事务和卸载逻辑仍由项目原有装配管理。公共外壳不创建第二套状态机,不导入项目的 platform.ts 或 localPages.ts。
  • 子应用只有独立运行时使用独立外壳;嵌入模式即使暂未连接 bridge,也不显示自己的头部、侧栏。独立菜单仍由本地 router meta 映射,不额外请求菜单接口。

配置与插槽的升级边界

HostShell 支持 brand(title、mark、workspaceTitle)、受控 collapsed、isFixedTab 展示规则,以及 brand、header-actions、message-trigger、messages、user-trigger、user-menu、header、sidebar、tabs 插槽。业务内容使用默认插槽。StandaloneShell 支持 brand、header-actions、sidebar 和默认内容插槽。

<HostShell :apps="apps" :tabs="tabs" :active-key="activeKey" user-name="张三"
  :brand="{ title: '业务工作台' }" @operate="operate" @open="open"
  @logout="signOut" @profile="openProfile">
  <template #header-actions><button @click="openHelp">帮助</button></template>
  <HostWorkspace />
</HostShell>

上例只示意展示扩展,实际项目继续使用生成模板中完整的属性、事件和认证接线。局部插槽不会把整个应用变成 custom;替换整个 header 后,仅该区域的默认展示升级不再体现,其他默认区域继续升级。插槽动作只发出事件,项目处理器仍必须执行原有核心授权和离页守卫;不得直接调用可信底层原语绕过事务。固定页签谓词也仅控制按钮,真正约束继续由项目的 workspaceOperation 实施。

头部消息通过两个独立插槽扩展;可只替换按钮或只替换内容,未覆盖的部分保留默认铃铛和原有空态。标准与自定义 host 模板的 HostLayout 均透传这两个插槽,项目可在 src/views/workspace/index.vue 的 <HostLayout> 上使用。

插槽作用域(HostMessageScope)默认内容
message-triggerexpanded、pending、toggle()、close()铃铛按钮
messages同上,仅展开时挂载消息标题与尚未接入消息服务的空态
<!-- 放在已有 HostShell 或模板 HostLayout 内,保留原有属性、事件及业务区。 -->
<template #message-trigger="{ expanded, pending, toggle }">
  <button type="button" :disabled="pending" :aria-expanded="expanded"
    aria-label="消息通知" @click="toggle">消息 {{ unreadCount }}</button>
</template>
<template #messages="{ close }">
  <ProjectMessageList :items="messages" @select="item => selectMessage(item, close)" />
</template>

unreadCount、messages、ProjectMessageList 与 selectMessage 由项目提供;消息接口、轮询或 WebSocket 不由外壳创建。项目可在点击处理后调用 close(),页面跳转继续使用项目现有的核心导航事务。toggle() 会检查 pending;自定义按钮仍应绑定 disabled 与 aria-expanded。弹层容器、内容滚动、点击遮罩、Esc、搜索/账号/页签菜单互斥和退出等待时关闭继续由外壳管理。内容插槽关闭时卸载,需长期保留的消息数据应放在项目状态中。

已有项目升级新版公共外壳即可在 HostShell 内使用消息插槽;要在生成的 HostLayout 外部传入,需补上上述两处插槽透传。custom 项目的本地 HostHeader 也需迁移这次模板改动,升级 npm 不会覆盖项目文件。

顶栏的 show-search、show-messages、show-user 均默认 true,分别控制搜索、消息和用户入口。关闭入口会卸载对应插槽并关闭已经打开的弹层。popover 继续由外壳内部维护,无需在项目中修改其类型。user-trigger 和 user-menu 可以分别替换账号入口和菜单内容;作用域类型为 HostUserScope,除 expanded、pending、toggle()、close() 外,还提供 userName、profile()、logout()。后两个动作先关闭弹层,再触发原有事件,项目继续复用导航和退出处理器。

<!-- 在已有 HostShell 内增加开关和插槽,其他属性、事件与业务区保持原有接线。 -->
<HostShell :apps="apps" :tabs="tabs" :active-key="activeKey" :user-name="userName"
  :pending="exiting" :show-search="false" @open="open" @operate="operate"
  @profile="openProfile" @logout="signOut">
  <template #user-menu="{ userName, close, pending, profile, logout }">
    <strong>{{ userName }}</strong>
    <button :disabled="pending" @click="profile">个人资料</button>
    <button :disabled="pending" @click="close(); openSettings()">账号设置</button>
    <button :disabled="pending" @click="logout">退出登录</button>
  </template>
  <HostWorkspace />
</HostShell>

openSettings 由项目实现。自定义用户按钮应绑定 :disabled="pending"、:aria-expanded="expanded" 并调用 toggle();关闭入口或 pending 期间,保留的 toggle/profile/logout 回调也不会触发操作。隐藏入口只影响展示,不改变权限。standard/custom 生成模板的 HostLayout 均透传三个显示开关及用户插槽,因此也可以在已有 <HostLayout :session="session" ...> 上使用。已有项目须同步这些模板接线;完整覆盖 header 时,顶栏由项目实现,显示开关仅作用于默认顶栏。

公共样式限定 .fin-micro-shell / .fin-micro-standalone,不写全局 body/reset,不把主页业务样式放进公共库。可在外层设置 --fin-shell-accent、--fin-shell-border、--fin-shell-muted;独立外壳还支持 --fin-shell-surface、--fin-shell-sidebar-width。Element Plus 与图标是 layout 入口的可选 peer;仅使用 core/SDK 不会导入布局、Element 或 CSS。按需指构建依赖隔离,不是 npm 选择性下载包内容。

已有项目接入

升级依赖不会自动改写已经复制到项目中的模板。已有 custom 项目需要一次性迁移:保留认证/host/runtime/router/业务工作区,将头部、侧栏和页签展示改为公共 HostShell,接回原有事件处理器,并导入公共 CSS;Vue 独立布局可改用 StandaloneShell。不要重新生成覆盖现有项目。迁移后,再次升级依赖才会同步公共外壳未覆盖区域。反向切换 custom 时,把当前版本布局源码复制到项目并改回本地导入,核心接线不变。

刷新启动占位

启动动画的结构与样式由生成项目根目录的 index.html 维护,不需要为了修改动画而升级运行库。保留外层 data-fin-startup="loading" 标记;需要自动更新国际化提示的文字节点保留 data-fin-startup-text 标记。启动逻辑首次读取并保存占位,后续挂载和失败重试克隆恢复;未提供占位时回退为文字。已有项目需要同步标记并升级到包含该逻辑的版本,不能仅修改模板文件。

公共 HTML 在模块加载前显示根节点内的启动提示;认证恢复和 router.isReady() 等待期间不提前渲染未授权工作区。Vue 挂载后自然替换。启动失败显示脱敏文案与重试,重试恢复 loading;取消可重试,旧导入、卸载后的按钮和迟到失败均受代次隔离。占位不使用 fixed 全屏遮罩,嵌入子应用只影响自身根区域。本次不是普通业务 HTTP 请求的全局遮罩,也不实现自动 Token 刷新。

按需获取当前 Token

import { getToken } from '@axewo/fin-micro/sdk'
const token = await getToken({ bridge, signal, timeoutMs: 5000 })
// 已登录 Cookie 模式返回 null;未登录、无桥、会话已变化均有独立错误码。

基座通过 createTokenCapability({ apps, getSession, provider }) 显式授权可信应用,每次读取私有凭据,异步后复查会话 revision 与调用存活。Token 不进入公开会话或事件广播。CLI host 模板默认保留 HttpOnly Cookie,后台 login/session 可选返回 accessToken;退出、初始化失败及卸载清除内存。base 请求只在安装 provider 后动态注入,vue bootstrap 在挂载时安装当前会话、卸载时取消并还原;嵌入时按桥能力协商凭据来源,独立时使用 apis/auth.ts 验证的会话。默认仅可信 /api/ 请求可携带 Token,绝对 URL 和被覆盖的 baseURL 不自动注入。

子应用生命周期与环境判断

import { isMicroFrontend, setupWujieLifecycle } from '@axewo/fin-micro/runtime'
import { mount, unmount } from './bootstrap'

// 仅检测当前 Wujie 环境,不代表 bridge 连接、身份或权限。
console.log(isMicroFrontend())
const dispose = setupWujieLifecycle({ mount, unmount })
if (import.meta.hot) import.meta.hot.dispose(dispose)

setupWujieLifecycle 统一注册 Wujie 回调、通知嵌入挂载、独立启动、pagehide 和幂等清理;重复注册会释放旧注册。pagehide.persisted === true 时保留实例与监听,避免 BFCache 返回后留下已销毁的应用;普通离开才释放注册和应用。Wujie 显式 unmount、dispose 与 HMR 清理不受 persisted 影响,不注册 unload,也不通过放宽 Permissions-Policy 掩盖警告。dispose() 返回 Promise,可等待清理完成。错误会报告至 console.error,显式调用生命周期回调可接收失败。bootstrap 自身仍须在 unmount 时使异步初始化失效,封装不能撤销回调内部副作用。SSR 检测为 false,注册不启动应用。环境检测不会把普通 iframe 或自行注册的挂载函数误认为微前端,不探测其他未适配的微前端框架。

基座使用普通启动入口,只有 vue 子应用模板接入上述封装;不再在 base 中注册子应用专属全局回调。

创建命令与项目维护

运行库与创建命令使用同一个包。交互创建或参数创建均可使用:

# 交互式:依次输入目录、选择 host/vue、选择布局、输入子应用 app-id 和端口
npx @axewo/fin-micro@latest create

# 参数式:适合脚本和 CI,不触发问答
npx @axewo/fin-micro create my-host --template host
npx @axewo/fin-micro create order-app --template vue --app-id order --port 7101

host 默认端口 7100,vue 默认端口 7101;项目名与 appId 只接受小写字母、数字和连字符。子应用示例建议指定 --app-id business,与基座默认登记保持一致;或调整基座的环境变量。目标目录必须不存在,父目录必须已存在;命令不覆盖文件、不自动安装依赖、不自动注册远端应用、不执行发布。进入生成项目后运行 pnpm install、pnpm dev 和 pnpm build。生成源码属于项目,CLI 不升级或覆盖既有源码。

基座多应用可信注册表

生成的 host 在 src/configs/microApps.ts 集中维护 microApps,standard/custom 共用同一配置。默认仅启用 business(http://localhost:7101),兼容 .env.local 的 VITE_MICRO_APP_ID/ENTRY;已附上注释的第二应用 report(http://localhost:7102),不会误加载尚未启动的地址。先创建并启动对应子应用,再取消配置注释。该示例实际读取 VITE_REPORT_APP_ENTRY,未配置时回退本机 7102;生产须在构建环境或 .env.local 设置自己的 HTTPS 入口,不能沿用 localhost。仅增加环境变量不会自动登记应用:

npx @axewo/fin-micro create my-report --template vue --app-id report --port 7102

注册项显式包含 appId/name/entry/shareToken。defineMicroApps 统一校验 appId 唯一、禁止宿主保留 host-local、入口 HTTP(S) 和地址安全规则;非本机入口必须 HTTPS。shareToken 必须为布尔值,业务和报表示例默认均为 false;确认完全可信且需要宿主认证后才显式开启。它只决定 Token 读取和认证失败上报能力,不决定应用或菜单授权;为 false 的应用仍可挂载和导航,但不能使用宿主 Token/失效协调,业务请求需采用自己的合法认证方案,不能把能力拒绝当成读取成功。能力白名单始终取当前会话应用与本地 shareToken:true 的交集,后台不能通过 entry 或 shareToken 字段改变代码地址或扩大凭据权限。

登记不等于授权:开发演示会为每个已启用注册项生成自己的菜单和 ${appId}:list 页签,并示范 /detail?id=1;真实模式的 /api/session 与 /api/login 返回 {user:{id,name},permissions:string[],appIds:string[],accessToken?:string},appIds 必须是注册表中的唯一子集。随后 /api/menus 必须完整返回 {apps:[{appId,menus:MicroMenu[]}]},每个已授权应用都要有一项,无菜单时传 [];未知、重复、未授权或遗漏的应用均拒绝初始化。分组为非空 children,叶子为 target,两者互斥;menuId 在应用内唯一、tabId 在整个宿主(含本地主页)内唯一,建议使用 ${appId}:业务标识。名称和 entry 始终来自本地注册表。

子应用 router.meta.hidden 仅控制独立运行的菜单展示,不影响基座后台菜单,也不授予或撤销页面权限。嵌入菜单由后台协议决定;详情等不展示入口在 platform/access.ts 的 canOpenRoute 显式授权,默认仅有带 demo:read 且具备 records 列表菜单的详情规则。详情策略优先于普通菜单,后台返回详情菜单也不能绕过;route 的数字 ID 必须与 tabId 一致。增加报表真实业务路由时同时替换演示菜单和详情规则,不能仅隐藏菜单来保护路由;后台 API 仍须校验登录、操作权限和资源归属。

业务功能目录

生成项目的业务页按功能聚合:Vue overlay 的 views/demo/index.vue 是 /list 列表装配层,views/demo/configs/table.ts 维护 fin-ui 表格/表单配置,views/demo/hooks/useRecordNavigation.ts 处理权限与详情导航,views/demo/types.ts 定义仅本功能使用的类型,views/demo/modules/detail/index.vue 是二级详情页。base 中被覆盖的计数页、demo store 与 demo 路由已移除。宿主的 views/login/index.vue 编排登录会话,表单展示位于 views/login/components/LoginForm.vue;主页、个人中心、工作区和 404 分别在各自的 views/{功能}/index.vue。按实际职责扩展 api/、configs/、hooks/、components/、modules/,不建立空目录或纯转发 hook。功能独有请求放功能 api/,可复用请求遵循项目约定放 src/apis;已生成项目的旧路径不会被包升级自动改写。

vue 独立布局与本地路由菜单

Vue 子应用独立运行显示头部、Element Plus 左侧菜单和内容区:standard 模式由公共 StandaloneShell 展示,custom 模式保留 layout/Header.vue、Sidebar.vue 和 StandaloneLayout.vue 本地源码;嵌入基座时均隐藏子应用头部和菜单。AppProviders 始终包裹全树,两种模式共用原业务页面、会话和 SDK 生命周期;嵌入继续使用原 MicroTabCache / MicroRouteView 及 tab.key 缓存契约。布局和 history 均使用 SDK isMicroFrontend() 判断 Wujie 环境,不以 bridge 是否连接、URL 或端口推断;缺桥的嵌入运行仍隐藏外壳并使用 memory history。

独立菜单由 router.options.routes 的本地声明树生成,不请求后台菜单,并按当前已验证会话过滤权限。meta.title 为回退菜单文字,titleKey 从 fin-locale 的业务映射翻译,permissions 声明访问要求,icon 为 Vue 图标组件(示例使用 @element-plus/icons-vue),order 按同级升序排列(默认 0,同值保留声明顺序),hidden 隐藏整棵菜单子树,activeMenu 指定活动菜单完整路径。默认登录后展示“主页 / 业务列表”,登录页隐藏;详情 /detail 设置 hidden: true, activeMenu: '/list', permissions: ['demo:read'],验证身份且具备权限后可访问并高亮列表。默认跳转、404、动态参数路由不生成菜单;无标题父级提升可见子项,有标题且有可见子项的父级递归显示 Element 子菜单,相对子路径拼为完整路径。菜单展示不代替路由准入;独立守卫与嵌入 MicroRouteView 均检查同一权限元信息,宿主仍负责 canOpen 授权。

生成后执行项目内的 check:runtime、typecheck 与 build,再验收独立与嵌入运行、菜单排序、权限过滤、递归菜单及详情高亮。库的 prepack 执行类型、构建和发布清单检查;这些检查不安装消费者项目依赖,也不代替业务浏览器验收。

host 本地登录与主页体验

使用 pnpm 12.3.4 安装时,生成项目自带 pnpm-workspace.yaml,通过 allowBuilds 仅批准 [email protected]、[email protected] 的安装脚本,不必为这两个版本重复执行 pnpm approve-builds。其他包或版本仍需审核,不启用全量脚本放行。已生成的项目须手动合并该配置;若项目已有 pnpm-workspace.yaml,保留原设置,只合并 allowBuilds,再执行 pnpm install。pnpm 低于 10.26 的版本需按其版本支持的方式授权;不要混用已移除的旧配置。

打开 Vite 输出的本机地址(默认端口 7100),在现有账号密码表单中使用 demo / 123456(开发模拟时默认预填),点击“演示登录,进入主页”。开发默认启用模拟登录,不需要后端或子应用,严格校验演示账号密码,错误或空凭据拒绝登录,成功后固定显示“演示用户”。此凭据仅用于开发模拟,请勿输入真实凭据;提交即清空密码输入,加载期间禁止重复提交。登录后默认打开真正的本地主页;左侧 Element 菜单、顶部搜索、个人菜单均可打开“主页 / 个人中心”。个人页展示公开身份,可回主页或退出。主页与 apps/micro-host 一样属于唯一 core tabs,而非独立入口或第二套标签状态:认证后在恢复前同步登记,初始、直链和刷新恢复均固定首位且不重复;缺少主页或主页顺序错误的旧快照自动迁移,业务页之间的顺序不变。主页无关闭按钮,右键菜单禁用刷新与关闭;“关闭全部业务页 / 其他 / 左侧 / 右侧”始终排除主页(个人中心也属于可关闭页)。业务页仍可正常刷新;关闭活动页在一次核心事务内回落主页,URL 经同一 Vue Router 更新,守卫拒绝则保持原页和 URL。不放置虚假业务数据或未实现业务按钮。

刷新仅凭当前标签页 sessionStorage 的 fin-micro:demo-session:v1=1 标记恢复固定演示身份,随后通过原 connectMicroBrowser 恢复已授权页签,产生新的生命周期 key。它不是 Token,不含账号密码,不访问认证接口。禁用浏览器存储时仍可登录,但无法跨刷新恢复。退出先显示一次系统 FDialog 确认;确认后清除演示标记与私有凭据,dispose 工作区,不逐页重复确认。认证失效也清除标记,组件卸载不清除标记以支持刷新。

如需真实后端联调,在 .env.local 设置 VITE_AUTH_DEMO=false。生产构建始终禁止演示,即使设置 true;请求 /api/session、/api/login、/api/menus、/api/logout,任何网络、认证或菜单失败均不降级演示。平台实现拆分到 platform/ 的 auth.ts、session.ts、menu.ts、access.ts,platform.ts 保留旧导出。权限最多 500 项,授权应用数不超过本地注册表,菜单响应必须完整覆盖,每应用最多 500 节点、8 层。生产平台登录/注销默认要求 configs/platformSecurity.ts 提供服务端 CSRF Token,缺失时拒绝发送;跨源凭据请求需要服务端配置精确来源、允许凭据与 CSRF 校验,不能使用通配来源。后台菜单只提供授权路由,应用执行地址来自可信本地注册表。

本地页使用明确的 { kind: 'local', appId: 'host-local' } 注册,禁止 entry;host-local 为宿主保留 appId,不能配置给远端应用。localPages.ts 固定 route/tabId 白名单,HostWorkspace 直接使用 HomeView/ProfileView SFC,Wujie 明确拒绝 local;不会把本地页面伪装成 HTTP 远端。两类页面复用同一 core 的标识、激活、关闭、刷新、守卫和 browser 恢复。远端仍按 appId 单实例挂载,Token 与 Auth 失败能力只向当前会话和本地 shareToken:true 注册表交集授权。可选业务入口需要启动子应用,但它离线不影响本地工作台。

scaffold/base 保存公共骨架,scaffold/host、scaffold/vue 按类型覆盖差异文件;两类模板统一接入 fin-ui。基座仅包含登录、公开用户信息、菜单与微前端平台编排,不包含系统管理业务。认证示例不是生产认证,需替换接口适配并补齐服务端鉴权;应用入口、appId、菜单权限需按实际配置。

运行库通过 npm 依赖导入,不复制 core 源码。公开包使用 files 白名单,仅交付运行库 JS、类型声明、创建命令与可公开的骨架源码,不交付运行库 src 或 sourcemap。编译 JavaScript 仍然可被分析,不应含密钥或保密逻辑。库升级需回归、构建、部署,无需重新创建项目;模板更新不会自动迁移生成项目。

生成项目的 src 统一保留 stores/router/layout/locales/hooks/utils/types/components/views/styles;Vue 子应用额外提供 apis/auth.ts 适配独立认证后端。每轮 bootstrap 创建独立 router、Pinia、fin-locale 与会话,卸载清理凭据读取、订阅和 history。AppProviders 直接使用 fin-ui 的 FinLocaleProvider,项目通过 src/locales/index.ts 统一组装业务词条、安装并返回 i18n,语言切换通过 @axewo/fin-locale。认证请求、地址校验和脱敏错误分类归 fin-core;会话、权限与启动生命周期归 fin-micro。utils 只保留兼容入口和业务配置,

地址栏修改仍经过基座 canOpen;子应用本地路由也通过统一公开身份检查 meta.permissions。独立模板统一先登录,列表不额外要求功能权限,详情要求 demo:read。前端准入不能代替后台接口的登录、操作权限与资源归属验证。standard 公共布局与 custom 模板仅面向桌面,使用 100vh 与工作区内部滚动,不提供移动断点或 dvh 适配。

host 真实路由与 URL 所有权

  • /login:真实登录路由;登录成功只允许跳转到当前会话已授权的内部目标,外链、协议相对地址、反斜杠、登录循环、未知或未授权目标均回落 /home。
  • /home、/profile:已认证工作区中的本地页;远端活动页使用 /micro/{appId}/{子应用内路径}?query,地址不携带页签标识;/workspace 仅作为工作区入口。/ 重定向主页,未匹配路径展示 404。
  • bootstrap 每个 App 仅创建一个 createPlatformSession(),一次恢复 Promise 供初始路由守卫等待;usePlatformSession() 仅注入,不重复 restore 或注册 401 监听。正常退出经一次系统确认再撤销会话、清理工作区并进入 /login;401 失效立即撤销,不被离页确认阻断。
  • host 的 connectWorkspaceBrowser 先登记固定主页,再使用 connectMicroBrowser(host, { url: false, initialLocation, storageKey }) 仅恢复/持久化用户隔离页签。router/workspace.ts 统一协调 Vue Router 和 core:UI 导航写入 router,直链/返回经过路由与页签守卫。连接器不再监听或覆盖 host 的 hash;未配置 url:false 的旧使用方式仍保留 hash 协议。
  • 首次深链优先于存储,恢复逐项经过 canOpen;整页刷新产生新的 core key,不恢复 Token、草稿或沙箱实例。生产服务器必须将 /login、/home、/profile、/workspace 及其他 SPA 路径回退到该应用 index.html,静态资源与 /api/ 不应被改写。子目录部署需同时配置 Vite base 和服务器回退目录。

交互关闭统一通过宿主 workspaceOperation 加上 exclude 与 closeFallback,不修改通用库的默认关闭规则。close/closeMany.closeFallback 是可选的生命周期引用:只在活动页被关闭且目标仍存活时同事务回落,不创建页面;旧 key 不复活重开页,页面 SDK 不能借它跨应用导航。正常退出单独确认后 dispose 工作区;真实失效直接清理全部,不被固定页策略阻断。固定不是权限或资源保留机制;底层宿主原语仍允许显式清理。模板与运行库需使用本次配套构建,不能仅更新模板沿用旧 dist。

host 统一路由守卫与扩展

router/guards.ts 是唯一 beforeEach 注册入口,执行顺序为:等待 controller.ready → 读取最新身份 → 登录与安全 redirect → 固定路由/远端授权和可选 meta.permissions → beforeEnter 业务扩展 → 当前 workspace 核心事务。router/index.ts 只声明路由并安装守卫,router/workspace.ts 使用 attachWorkspaceGuard 挂接现有 core operate/beforeLeave,不再注册第二个前置守卫。未登录受保护页进入 /login?redirect=...;已登录访问 /login 只返回经过 authorizedRedirect 检查的内部授权目标。404 保持独立兜底;已登录工作区离开到 404 仍须通过业务未保存确认。

公开结构:

  • installHostGuards(router, controller, options?) → dispose:每个 router 只允许一个安装;返回幂等撤销函数。
  • HostGuardOptions.beforeEnter({ to, from, session, signal }) → boolean | void | Promise<boolean | void>:在内置授权后执行,返回 false 取消,true/void 继续;抛错或拒绝会取消并报告,不能凭扩展放宽内置白名单。
  • HostGuardOptions.onError(error):供宿主脱敏展示,不直接把原始异常写入 UI。
  • attachWorkspaceGuard(router, delegate) → detach:只供工作区桥接核心离页事务,重复连接拒绝;卸载撤销旧委托,不能通过组件另建 beforeEach。
  • createAppRouter(controller, history?, options?) → router & { disposeGuards() }:bootstrap 在卸载、启动失败和重挂载时显式撤销守卫,再销毁 history。

可在 bootstrap 的原 createAppRouter 调用处增加业务限制,不要另调 router.beforeEach:

const router = createAppRouter(controller, undefined, {
  onError: reportError,
  beforeEnter: ({ to, session, signal }) => {
    if (signal.aborted) return false
    // 示例:业务条件只能进一步限制已获本地路由白名单授权的入口。
    return to.path !== '/profile' || Boolean(session.user.id)
  },
})

路由记录可加 meta: { authenticated: true, permissions: ['demo:read'] },表示必须具备全部声明权限;生产替换为真实权限码,同时补齐本地 route/tabId 白名单与页面映射,不能仅靠 meta 添加任意受保护页面。该前端检查不代替后台授权。

新导航、身份替换或撤销会中止旧守卫等待;每次异步边界后复查导航代次和身份对象,迟到恢复/扩展结果不能放行旧导航。取消信号只撤销导航等待,不自动取消已经发生的保存或外部副作用。正常退出先完成一次系统确认;真实失效及注销撤销身份后跳过旧 workspace 委托,优先清理资源。首次恢复提交身份属于 ready 本身,不会误取消首次直链或刷新导航。

启动依赖门禁

生成项目在 npm run dev/build 前自动执行 scripts/check-runtime.mjs,也可单独运行 npm run check:runtime。它加载实际安装包并校验模板使用的导出,host 额外要求 @axewo/fin-micro 导出 hostRouterProtocol === 1(local、认证能力、仅存储连接器),缺失时在 Vite 链接前明确报告模块/API。版本号由生成器实际 package.json 注入;同版本的旧构建仍可能缺能力,不能靠版本字符串保证可用。请安装配套构建的 core/UI/micro 包,模板不会自动升级或降级依赖,也不能以源码 alias 验证代替实际安装验证。直接运行 vite 会绕过 npm 的前置门禁,不推荐。

公共启动入口 @axewo/fin-micro/startup 支持 { development: true } 显示固定阶段和白名单错误名;默认关闭,生产保持脱敏。界面不回显原始异常 message、Token、请求/响应或堆栈。配置类错误需核对公开环境配置;能力门禁不代表后端连通性或接口协议正确。

公共配置、错误边界与登录失效

公共 utils/appConfig.ts 集中校验 VITE_API_BASE(默认 /api/)、VITE_API_TRUSTED_BASE(默认与 API 一致)、VITE_API_TIMEOUT(默认 30000 毫秒)及 VITE_API_CREDENTIALS(仅接受字符串 true/false,默认 false)。两个 API 目录必须完全一致、以 / 结尾;拒绝 userinfo、查询、片段、路径穿越及编码分隔符。跨源生产网关与应用代码入口使用 HTTPS,本机开发允许 HTTP。环境变量是公开部署配置,不能包含秘密。跨源 Cookie 需后端精确 CORS 与 CSRF 防护;默认相对 API 属于当前子应用运行源,并非自动代理到宿主。

utils/errorUtils.ts 将 Axios/HTTP/SDK 错误统一映射为取消、未登录、无权限、超时、网络及未知错误。界面与日志仅消费固定安全文案,不展示原始 message、响应体、URL、头、Token 或堆栈;取消静默。Vue errorHandler、登录表单、导航与连接失败使用相同分类。入口动态加载 bootstrap,因此模块加载/配置校验错误也有纯文本启动兜底与重试;卸载使晚到导入失效,失败与重挂载继续清理 router/Pinia/凭据订阅。构建配置错误需要更正环境并重新构建/刷新;重试不保证浏览器重新求值已失败的 ESM 模块。

Vue 嵌入时协商并安装 getToken/beginAuthRequest/reportAuthFailure。createAuthFailureCapabilities 是 SDK 正式契约,复用 callHost 白名单和生命周期;每次可信请求先获取不含凭据的不透明内存票据,绑定宿主私有凭据版本与可信 appId。401 或 Token 未登录按原票据报告,宿主核验后立即撤销身份、推进版本;并发仅失效一次,旧响应不能退出新登录。票据不得复制、序列化、持久化或用于 iframe RPC。平台自身请求也在发送时捕获私有版本。正常主动退出经一次系统确认,真实认证失效不允许被未保存守卫阻止。模板不刷新 Token、不自动重放任何请求,也不新增总线或请求库。

独立 Vue 应用通过 src/apis/auth.ts 接入真实会话、登录、恢复和退出。模板内置 /login 登录页,成功后进入 /home 主页;账号密码登录不再使用弹窗,菜单由本地路由生成,不请求后台菜单。未登录与会话失效回到登录页,功能权限不足显示 403。开发服务器独立运行时顶栏仍提供「开发设置」,Token 经 GET /api/session 验证后保存到按 appId 隔离的 localStorage;刷新自动验证恢复,无需重复设置。清除、退出和当前请求 401 删除本地值;卸载保留它以支持刷新。生产构建和宿主嵌入均不读取开发 Token 存储。嵌入时不注册独立登录页、主页,身份和菜单仍来自宿主。基座自己的 DEV 演示身份配置保持原协议,真实接口失败不会降级为演示登录。

平台认证适配器与模板更新

@axewo/fin-micro/vue 导出 createPlatformAuth,创建时提供直接返回响应体的独立认证请求客户端 http 和公开客户端标识 clientId。默认使用 auth/code、auth/login、system/user/getInfo 和 auth/logout;可通过 paths 覆盖,通过 parsers 转换完整响应体,或通过 identity 转换默认响应中的身份数据。认证客户端不能使用依赖当前会话的凭据拦截器,否则登录可能等待自身会话。验证码通过 loadCaptcha(signal) 获取,登录通过 signIn(session, username, password, answer?) 交由公共会话管理;适配器本身不会自动接入生成项目,需在项目认证配置中显式装配并验证后台协议。

默认响应要求状态码为 200,登录返回有效访问令牌、匹配的客户端标识及有效期,随后验证用户身份;验证码仅接受受限的图片格式。自定义转换结果仍经过校验。认证和权限校验不能替代服务端鉴权,不要将凭据放入前端环境变量。

新生成模板的开发服务器提供 @ 源码别名,并根据 VITE_API_BASE、VITE_API_AUTH_BASE 和 VITE_API_PROXY_TARGET 配置开发代理;代理仅在开发时生效,生产网关需自行配置。模板补充图标及类型依赖,调整启动动画颜色,并将独立登录页表单逻辑移至功能目录的钩子。已有项目不会因升级依赖自动更新这些文件,应按需合并并重新检查、构建。

认证模式、启动就绪与运行状态

子应用公开配置 VITE_MICRO_AUTH_MODE 支持 auto(默认)、host、independent。auto 在宿主完整授权 getToken/beginAuthRequest/reportAuthFailure 时接入宿主认证,三项均未授权时使用应用自己的认证;只授权部分能力会明确失败。host 必须获得全部能力;independent 不读取宿主 Token。三种模式仍校验桥协议,独立认证也不授予任何业务权限。这样 shareToken:false 的子应用可正常挂载,但独立认证接口及权限由项目实现。

createWujieRuntime(host, { waitForReady: true, mountTimeoutMs: 30000, readyTimeoutMs: 30000 }) 将资源启动与业务初始化分开等待。资源阶段完成后,子应用通过 setupWujieLifecycle 在异步 mount() 完成时回报就绪,失败回报 BOOTSTRAP_FAILED。入口自行捕获初始化异常时,须调用 /sdk 的 getMicroAppLifecycle()?.fail();模板启动边界已接入。旧应用未实现回报时保留默认 waitForReady:false,不要直接开启等待。

返回的 runtime 增加 getState(appId) 和 subscribe(listener),快照包含 appId/attemptId/status/elapsedMs/errorCode。状态依次反映 loading → initializing → ready,卸载为 unmounting → idle,失败为 failed。错误码包括 LOAD_FAILED、LOAD_TIMEOUT、READY_TIMEOUT、BOOTSTRAP_FAILED、MOUNT_CANCELLED、UNMOUNT_FAILED。订阅仅通知后续变更,监听器异常不改变挂载结果。每次重试使用独立回报通道;旧实例晚到的回报不能覆盖新尝试。operate() 提交导航仍不等于应用就绪,加载与失败展示使用 runtime / MicroAppContainer。

公共工作区与运行时资源治理

导航先准备再等待 Router 成功后提交,覆盖 beforeEnter、异步组件和 beforeResolve 拒绝;取消排队任务立即结束。宿主新增 navigationTimeoutMs(120000ms)和 maxPendingNavigations(100),分别报告 NAVIGATION_TIMEOUT 和 QUEUE_FULL。

运行时支持 unmountTimeoutMs(5000ms)、maxMountedApps(16)和 maxConcurrentMounts(4),通过 getResources() 读取实例、加载与残留沙箱数量。预算不足以 RESOURCE_LIMIT 拒绝,不自动关闭脏页。每次挂载注入独立可撤销 bridge,旧实例的 PageSDK、订阅和未提交调用随卸载释放。原始 Wujie 异常统一转为 MicroRuntimeError,销毁异常/超时为 UNMOUNT_FAILED/UNMOUNT_TIMEOUT。

卸载超时结束公开等待并隔离旧 DOM,不代表强制终止第三方 JavaScript;不能确认清理完成的沙箱继续计入预算。

模板与运行库保留同一发布包,通过 sdk/core/runtime/vue 子入口维护边界。useMicroWorkspace(apps, { host, runtime, onError }) 统一创建宿主、运行时及关闭重开代次 epochs;own(cleanup) 登记连接器释放,dispose() 幂等且立即撤销宿主能力,再异步销毁沙箱。Vue 组件卸载自动清理。connectMicroHostRouter(host, router, options) 处理核心事务与 Vue Router 同步,并在断开时取消挂起导航;认证守卫注册、路由映射、固定页策略仍由项目回调提供。后台接口、菜单和业务权限继续保留在生成项目。

生成项目的 fin-micro.json 记录模板版本、生成器版本、布局与应用标识。已有项目应按实际源码完成迁移,不要仅修改版本标记。可在项目目录执行以下只读检查:

npx @axewo/fin-micro@latest doctor .

doctor 离线只读检查模板身份、appId、安装依赖可解析性以及 SDK/Vue/runtime 实际能力;失败返回非零状态,不自动改文件或联网安装。它不检查后端权限、部署入口、CORS/CSP 或浏览器兼容性,这些仍由联调验收负责。

离页守卫的等待上限

createMicroHost(apps, { guardTimeoutMs: 60000 }) 为每个异步守卫设置等待上限。超时以 NavigationError.code === 'GUARD_TIMEOUT' 取消本次导航,不自动放行、不重试保存。宿主销毁立即以 HOST_DISPOSED 结束挂起守卫,调用方取消同样释放队列。beforeLeave(({ signal }) => ...) 的信号可传给保存请求以协作清理;迟到结果不能提交已取消的导航,已经发生的服务端副作用仍由业务处理。

未保存表单

import { useUnsavedChanges } from '@axewo/fin-micro/vue'
const { dirty, setBaseline } = useUnsavedChanges(() => form, {
  label: '基础信息',
  message: { title: '离开编辑页?', content: '修改尚未保存,是否放弃?' },
})
// setup 调用一次,自动追踪字段;查询赋值后 setBaseline()。
// 保存成功后 setBaseline(本次提交的独立快照),保存失败不重置。

模板通过 installMicroConfirmation 与项目 ConfirmationDialog.vue 统一使用 fin-ui FDialog。嵌入页面按固定 tab.key 登记,不把表单数据传给基座;缓存页签切换不提示,关闭/刷新/替换时聚合一次确认,批量关闭列出所有受影响页面。独立运行由 connectUnsavedChangesRouter 保护路由切换。退出只进行一次系统确认,取消保留原状态,确认后直接清理工作区,不重复执行逐页守卫。第二参数支持 enabled/formId/label/message,文案可用 getter;content/html 二选一,富文本经受限标签清理。

响应式权限示例

新生成的 host/vue × standard/custom 模板已注册 v-hasPermi,列表的「打开详情」按钮使用 demo:read 演示显隐。已有项目需在当前 app.mount 前补充注册;installMicroSession 不会自动安装指令:

import { installMicroSession, installPermissionDirectives } from '@axewo/fin-micro/vue'

// 沿用 bootstrap 中当前 app 和 createBridgeSession() 得到的 session。
installMicroSession(app, session)
installPermissionDirectives(app, session.identity) // 传 ref,不传 .value 快照

host 使用平台控制器:installPermissionDirectives(app, () => controller.session.value ? publicSession(controller.session.value) : null),其中 publicSession 从项目的 ./platform 导入。每个 App 注册一次并使用自己的响应式会话,嵌入子应用沿用桥同步,无需重新请求或复制权限。

<template>
  <el-button v-hasPermi="'button_001'">查看</el-button>
  <el-button v-hasPermi="['button_002', 'button_003']">新增或删除,任意一项满足即可</el-button>
</template>

字符串表示单项,非空合法数组表示任意一项;标识全局唯一即可,不要求「应用:资源:操作」格式。已认证会话的 permissions: ['*:*:*'] 表示管理员,放行全部有效标识,*、order:* 没有此含义。未登录、空白绑定、空数组或含非法项的数组均隐藏,管理员也必须使用有效绑定。

指令随登录、授权、撤权和退出更新,通过 CSS 隐藏并在授权后恢复原 display,组件仍会创建;只用在原生元素或单根组件(如 el-button),不与同元素 v-show 混用。需要全部权限或不创建组件时使用 v-if:

import { computed } from 'vue'
import { usePermission } from '@axewo/fin-micro/vue'

// setup 中默认使用 installMicroSession 注入的身份;也可显式传 identity ref/getter。
const permission = usePermission()
const canRead = permission.can('demo:read')
const canEdit = computed(() => permission.hasPermission('demo:write'))
const canUse = computed(() => permission.hasAny(['demo:read', 'demo:write']))
const canManage = computed(() => permission.hasAll(['demo:read', 'demo:write']))
<template>
  <el-button v-if="canRead">有权限时才创建</el-button>
  <el-button v-if="canManage">同时拥有读取和写入权限</el-button>
  <el-button :disabled="!canEdit">保留展示,无权限时禁用</el-button>
</template>

框架无关逻辑首选从 @axewo/fin-core/permission 导入 hasPermission(session, name)、hasAny(session, names)、hasAll(session, names);/sdk 同名函数保持兼容并调用 core。Vue 权限变更/退出立即更新计算值;普通函数在 computed/模板内调用才追踪依赖,不要把单次布尔结果当作响应式状态。按钮显隐仅辅助体验,核心 canOpen 和服务端仍须独立鉴权。

locales / router / stores 接线

两类生成项目均包含 locales/modules/app_zh-CN.ts、locales/modules/app_en.ts 与各自的真实路由。业务词条按 模块名_语言.ts/json 命名,例如 User_zh-CN.ts 导出 { name: '姓名' },对应 t('User.name')。locales/index.ts 自动收集并按语言和模块命名空间合并,调用 installFinI18n(app, { messages }) 注入公共与业务词条,默认导出 setupI18n(app) 并返回当前应用的 i18n;页面使用 useFinLocale 切换语言。语言入口从 FConfigProvider 的 config.langs 读取选项,AppProviders 透传该配置,未配置时默认中英文;扩展语种支持选择、保存和宿主同步,缺失文案默认回退中文。宿主和独立 Vue 应用在首次渲染前通过 connectFinLocaleStorage 恢复语言,切换后立即保存,卸载释放观察。存储键分别为 fin-micro:locale:host:<项目名> 和 fin-micro:locale:app:<appId>,避免互相覆盖;存储被禁用时保留内存切换。嵌入子应用只通过 connectMicroLocale 跟随宿主偏好,不读写独立语言存储,也不改变认证版本。已有项目需要升级配套包并迁移 bootstrap 接线,每轮挂载创建独立 Pinia,已移除未使用的计数 store、router/demo.ts 和 /demo 入口。

  • vue 独立运行:启动后先在 /#/login 登录,再从主页菜单进入 /#/list(默认端口 7101);列表/详情与缓存接线保留。
  • vue 嵌入基座:后台 /api/menus 须为当前已授权应用返回列表入口,例如 { menuId: 'records', name: '示例记录', target: { tabId: 'business:list', route: '/list' } }(替换实际 appId 前缀),再从基座菜单打开;未授权深链仍被拒绝。
  • host 本地扩展:在 host 的 router/index.ts 添加真实路由记录及认证元信息,并在 router/targets.ts 补充固定路由到 core 页签的映射;工作区页面还需补充 localPages.ts 的精确白名单及 HostWorkspace.vue 的显式 SFC 映射。本地路由不能代替平台授权。

业务添加 store 后,组件外显式传所属 Pinia 实例,组件内由已安装的 Pinia 注入。多页签属于同一子应用时共享该应用的 store;需要按页签隔离的业务状态应显式按页签标识管理。

包入口

入口用途
/sdk框架无关类型、桥获取、调用/导航契约
/core应用登记、宿主状态、导航事务与能力白名单
/runtimeWujie 单 appId 单实例挂载和清理
/vueVue 容器、路由连接、页签缓存与页面 SDK
/browser基座 URL 和公开导航元信息恢复
/iframe显式窗口来源校验的独立 RPC

非 Vue 应用使用独立子入口;根入口包含 Vue 适配。

Vue 子应用在本地维护正常 Vue Router 路由表,基座只传递 appId 和应用内 route,不传组件文件路径。缓存内容直接使用 MicroRouteView,不必复制路由解析器:

<MicroTabCache :tabs="tabs" :active-key="activeKey">
  <MicroRouteView />
</MicroTabCache>

MicroRouteView 需要应用安装 Vue Router ^4.5.0 并调用 app.use(router);提供固定页面路由上下文、懒加载、路由记录 redirect、可见错误及重试。它不执行全局导航守卫、不修改宿主页签;嵌入模式不要同时对每个页签调用共享 router.replace,跳转和离页确认仍使用 PageSDK。

使用前必须知道

  • 同 appId 只运行一个实例,应用内通过不同 tabId 打开多个路由页;key 代表具体页面生命周期。
  • openTab/operate 保持应用隔离;跨应用打开使用 page.navigateTo,由宿主 canNavigate 显式授权并继续检查 canOpen。
  • 功能页关闭使用 sdk.back(target?):传完整 OpenTab 时优先去指定目标,不传则返回来源;跨应用来源返回须宿主 crossAppBack: true(模板已开启)。中间来源关闭后跳过至存活祖先,页签栏关闭规则保持现状。显式跨应用目标检查 canNavigate/canOpen,来源返回只复核 canOpen;拒绝时保留本页。
  • 参数迁移: 旧版 sdk.back(input) 的 input 是 fallback,本版改为显式优先目的地。需要旧行为时使用 sdk.operate({ type: 'back', fallback: input })。使用示例、结果处理、协议能力检查与生命周期边界见功能页面关闭。
  • 导航 committed 不代表资源加载完成;运行时错误与重试另行处理。
  • 公开会话不带 Token,宿主能力使用显式白名单;同窗口桥不是恶意代码安全沙箱。
  • 超时/取消不回滚业务副作用;缓存和 sessionStorage 导航恢复不代替草稿持久化。
  • iframe RPC 不是完整 AppBridge、守卫或缓存的透明代理。

生产构建与接入检查

pnpm check:production
pnpm --filter @axewo/fin-micro typecheck
pnpm --filter @axewo/fin-micro build
pnpm --filter @axewo/fin-micro check:package

测试用例及临时验收工程已移除。类型、构建、公开入口、模板运行能力和发布清单检查继续在 prepack 与 CI 中执行;静态检查不能替代真实后台和浏览器业务验收。

模板版本为 3,使用纯路径路由,生成项目固定使用当前配套 UI 版本;源码生成读取 core/locale 的实际 workspace 版本,打包后使用 pnpm 改写的依赖版本。已有工程仍需按文档同步源码,再执行 fin-micro doctor 和生成项目内的 check:runtime。

生产部署的 HTTPS、路由回退、CORS/CSP、认证及后台权限按项目环境验收。

版本与发布记录

@axewo/fin-micro 共发布 20 个版本,首次发布于 2026/10/19;过去 12 个月发布了 20 个版本。

版本发布日期距今
3.0.15latest2026/11/052 天前
3.0.142026/11/052 天前
3.0.132026/11/052 天前
3.0.122026/11/052 天前
3.0.112026/11/043 天前
3.0.102026/11/043 天前

关于 @axewo/fin-micro 的常见问题

@axewo/fin-micro 是什么?

在线文档

如何安装 @axewo/fin-micro?

在项目目录运行 npm install @axewo/fin-micro,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 fin-micro,可以用 npx fin-micro 直接运行。

@axewo/fin-micro 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@axewo/fin-micro 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@axewo/fin-micro 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@axewo/fin-micro 可以商用吗?

@axewo/fin-micro 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@axewo/fin-micro 的下载量有多少?

根据 npm 官方下载统计,@axewo/fin-micro 在 2026/10/08 – 2026/11/06 这 30 天内被下载 3,011 次,日均约 100 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@axewo/fin-micro 还在维护吗?

最新版本 3.0.15 发布于 2026/11/05(2 天前);至今共发布 20 个版本,其中过去 12 个月发布了 20 个;首次发布于 2026/10/19。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。