为什么要做微前端:从品茗旧项目的接入痛点,到统一 SDK
以前想做一个微前端奈何前端组成员基础知识过于薄弱无法推动执行,我们的项目有将近200个,每个项目还不一样,覆盖vue2、vue3、jsp、react编码也是各种形形色色,这次有了AI大家水平提升了,我决定推动下这个的执行
在业务系统持续扩展的过程中,前端往往会从一个应用逐渐发展为多个应用:不同团队分别维护项目管理、客户服务、设备管理等模块,有的采用 Vue 3,有的仍然使用 Vue 2。各个系统可以独立开发,但进入统一平台后,又需要共享登录状态、响应平台导航,并在页面切换时正确管理资源。
一、为什么要做微前端:业务已经拆开,协作规则还需要统一
回看过去的项目,我们已经形成了招标文件编制、评标、开标、监管、门户和 AI 工具等多个工程。它们在不同阶段建设,承担不同业务,也积累了各自的登录、路由、缓存和交付方式
无界微前端
本次封装的sdk使用的无界微前端封装,

二、SDK 在整个框架中承担什么角色
品茗微前端框架由主应用、SDK 和业务应用共同组成。主应用负责平台入口与应用调度,业务应用负责页面和业务逻辑,SDK 负责双方之间的连接与协作。
| 组成部分 | 主要职责 |
|---|---|
| 主应用 | 注册和加载应用,维护菜单,处理平台认证、导航授权与上下文发布 |
| 微前端 SDK | 统一接入协议,协调生命周期,传递上下文、业务消息和平台请求 |
| 标准模板 | 提供 Vue、路由、状态管理、请求封装、布局和 SDK 接入示例 |
| 业务项目 | 实现业务页面、接口调用、业务权限、状态管理与资源释放 |
SDK 基于无界环境建立主子应用连接,但不负责创建或初始化无界实例。它的核心没有运行时依赖,也不打包 Vue、Axios、Pinia、Vuex 或组件库,因此业务项目可以继续使用自己的技术栈和工程组织方式。
这种分工让接入规则能够集中维护。业务团队通过统一 API 使用平台能力,主应用也可以用相同协议管理不同的业务应用。
三、统一生命周期,让应用可靠地进入和离开平台
微前端中的应用会经历首次加载、切换、保活恢复、卸载和重新挂载。尤其在初始化包含异步请求时,用户可能已经切换页面,而旧请求才刚刚返回。
SDK 通过 defineMicroApplication 协调这些过程。业务项目提供 mount、unmount、activate 和 deactivate 等回调,由 SDK 连接无界生命周期,并按顺序处理相关操作。对于重复触发的挂载,SDK 会合并正在进行的任务,减少重复初始化。
每轮挂载还会创建独立的资源作用域 scope。项目可以将事件解绑、定时器清理、请求取消和应用销毁函数登记到其中,卸载时统一释放。清理按照后登记先执行的顺序进行,单个清理函数失败不会阻断其他清理。
例如,在一次业务页面初始化中,可以先登记请求取消函数,再等待数据加载;等待结束后检查 scope.active,只有当前挂载仍然有效时才继续渲染。这样能够降低旧请求返回后继续操作已卸载页面的风险。SDK 提供作用域和清理机制,业务项目仍需主动登记资源,并检查异步流程是否已经失效。
保活场景也有明确区分:停用时,项目可以在 deactivate 中暂停轮询或动画;恢复时,再在 activate 中启动。保活停用不会自动销毁应用,最终卸载时才执行对应的资源清理。
此外,SDK 会在异步挂载完成后通知主应用就绪。主应用可以通过 onReady 安排后续导航或收起加载界面,避免仅凭容器加载事件判断业务初始化已经结束。
四、统一上下文,让身份和业务环境保持同步
多个业务应用接入同一个平台后,需要知道当前用户是谁、所属租户是什么,以及平台传入了哪些业务参数。SDK 将这些信息组织为统一的应用上下文。
上下文包含组织信息、租户标识、用户身份、角色、权限码和业务扩展数据,同时携带应用标识、实例标识、协议版本及修订号。
主应用使用 host.updateContext() 发布变化,子应用通过 client.getContext() 读取当前快照,并通过 client.onContext() 订阅后续更新。例如,用户在平台切换账号或租户后,主应用向需要更新的应用发布新上下文;子应用收到通知后,清理旧业务状态并重新加载对应数据。
为了减少状态同步中的歧义,SDK 对上下文做了两项处理:每次更新递增修订号,子应用忽略旧版本通知;读取和通知时提供 JSON 副本,避免某个应用直接修改数据后影响其他接收方。
业务扩展字段必须是可序列化的 JSON 数据。组件、Store、函数和请求实例不适合通过上下文传递。上下文中的身份信息用于前端展示与交互协作,实际接口访问仍由后端完成鉴权,角色和权限码的业务含义由平台与项目约定。
五、双向业务通信,让主子应用协作更清晰
除了平台统一的上下文,业务应用还需要发送自己的事件。例如,子应用完成一项操作后通知主应用刷新统计,或主应用通知当前子应用刷新列表。
SDK 在主端和子端都提供了 on 与 emit 方法。双方约定事件名称,使用 JSON 数据作为消息内容,即可完成双向通信。每次订阅都会返回解绑函数,便于纳入页面销毁或应用卸载流程。
通信通道按应用标识和实例标识区分,同时区分主到子、子到主两个方向。同一业务应用需要并列运行多个实例时,可以配置不同的 instanceId,并在无界侧使用不同的实例名称,减少消息误串。
这里的实例命名空间用于区分消息接收范围,不构成安全隔离或后端权限控制。业务事件也没有离线缓存和自动回执;涉及明确成功或失败结果的平台操作,应使用对应的请求 API。两个子应用之间的业务协作,可由主应用按业务规则接收并转发消息。
六、统一导航请求,串联跨应用业务流程
跨应用跳转是统一工作台中的常见需求。例如,用户在项目中心查看一条记录后,需要进入设备管理应用中的对应详情页。
SDK 允许子应用通过 client.navigate({ appId, path }) 提交导航意图。子应用只需说明目标应用和内部路径,主应用负责核对应用是否已注册、用户是否可以访问,并安排目标应用的加载。
目标应用就绪后,主应用通过 host.navigate(path) 下发路径。子应用在 onNavigate 回调中调用自己的 Router,从而完成实际页面切换。应用内部的普通跳转则继续使用项目自身的路由接口。
这种分工使业务页面不必掌握其他应用的部署地址,也不必自己管理加载实例。对于尚未加载的目标,主应用需要暂存导航意图,在 onReady 后下发;SDK 不会自动缓存和重放这些导航消息。
SDK 会校验路径格式,拒绝外部 URL、协议相对 URL 等不符合约定的输入。目标路由的业务权限仍由主应用和项目判断。另外,导航请求的 Promise 完成表示主应用已处理请求,不代表目标页面已经渲染完成。
七、身份操作统一交给平台处理
在统一平台中,各个子应用经常需要发起登录、退出或报告会话失效。SDK 为此提供三个明确的接口:
| 接口 | 使用场景 |
|---|---|
requestLogin(returnPath) |
请求平台发起登录,并携带应用内返回路径 |
requestLogout() |
请求平台执行退出流程 |
reportUnauthorized() |
业务接口确认登录失效后,通知平台处理 |
主应用在 onRequest 中接收这些请求,调用自己的认证服务,并通过上下文发布身份变化。子应用不能通过发送一个自建的用户对象来改变主应用身份。
当多个业务请求同时发现会话失效时,reportUnauthorized() 会在同一上下文修订内去重;通知失败后允许重试。这样可以减少同一失效状态下反复触发平台处理的情况。
SDK 提供的是身份操作的请求与通知协议。真实 SSO、登录接口、Token 管理和业务会话清理,由主应用或项目的认证适配层实现。
八、按应用、用户和租户管理业务缓存
列表筛选条件、页面偏好等数据适合缓存在浏览器中,但不同账号和租户之间需要明确区分。
SDK 提供可选的 createScopedStorage,以应用、用户和租户的组合创建缓存命名空间,并提供 get、set、remove、clear 四个方法。
例如,用户在某个租户下保存的筛选条件,可以与另一租户下的筛选条件分开。调用该作用域的 clear() 时,只删除对应范围内的键,不会清空浏览器中的全部存储。相同应用、用户和租户组合的多个实例会共享这份缓存。
存储介质由项目显式传入,可以使用 sessionStorage、localStorage 或相同接口的实现。切换用户或租户后,需要创建新的存储作用域;旧缓存是否删除由业务项目决定。该能力适用于非认证业务数据,不提供加密,也不用于保存密码、Token 等登录凭据。
九、兼顾独立开发与嵌入运行


业务应用需要在平台内运行,也需要在本地独立开发和调试。SDK 能识别当前是否处于无界嵌入环境,并为两种模式提供相应行为。
嵌入模式下,SDK 校验主应用连接、应用标识和协议版本,然后建立通信。独立模式下,仍可使用生命周期与资源清理机制,业务页面、接口和独立认证由项目自行管理。
依赖平台的消息发送、登录请求和跨应用导航,在缺少可用主应用连接时会明确报错。业务页面可以通过 client.embedded 判断运行模式,为这些入口提供合适的显示与提示。
仓库中的 Vue 3 和 Vue 2 标准模板使用同一套 SDK。新业务默认采用 Vue 3 / TypeScript;明确要求 IE11 的项目使用 Vue 2 / JavaScript 模板,并以独立访问 Vue 2 子应用的方式规划。真实 IE11 运行仍需项目验证,SDK 安装或静态兼容检查不能替代浏览器验收。