无界 Wujie 微前端实战:三步接入、三种模式与高频坑的完整指南
无界 Wujie 微前端实战:三步接入、三种模式与高频坑的完整指南
【免费下载链接】wujie极致的微前端框架项目地址: https://gitcode.com/gh_mirrors/wu/wujie
无界(Wujie)是一款基于 Web Components + iframe 的微前端框架,核心思路是把子应用"原生隔离"地装进主应用页面:样式靠 Web Components(浏览器原生的组件封装技术)隔离,JS 在 iframe(浏览器原生的隔离小窗口)里运行,两边互不污染。它对子应用几乎零侵入,存量老项目也能直接用。
如果你有下面两种情况,这份实战就是为你写的:
- 多团队各维护一套应用,想并入同一套系统,但技术栈没法统一
- 有一批不想(也没法)动的老应用,需要嵌进新门户里
💼 为什么不用 iframe 直接套?
纯 iframe 嵌入看似省事,实际有三个绕不开的问题:
- 隔离太彻底:JS、路由、DOM 全关在 iframe 里,主应用够不着,跨窗口通信很别扭
- 体验割裂:弹窗盖不住整页,路由跟浏览器地址栏不同步,刷新丢状态
- 切换慢:每次切页面都重新请求资源,白屏时间不受控
无界的解法可以一句话讲清:Web Components 管 DOM,iframe 管 JS。DOM 留在主应用这一层,所以弹窗能覆盖整页、样式原生隔离;JS 仍跑在 iframe 里,执行环境同样天然隔离。两个都是浏览器原生能力,比自造沙箱的微前端方案省掉大量边界问题。
🔌 三步完成主应用接入
Vue / React 主应用可以直接用 wujie-vue、wujie-react 封装组件,这里给原生函数写法,逻辑完全一样:
import { setupApp, preloadApp, startApp } from "wujie"; setupApp({ name: "sub-app", // 子应用唯一标识 url: "http://sub.example.com", // 子应用地址 el: "#container", // 挂载容器 sync: true, // 路由同步,刷新不丢路由 alive: true // 保活模式 }); preloadApp({ name: "sub-app" }); // 预加载资源,可加 exec: true 直接预执行 startApp({ name: "sub-app" }); // 启动并渲染子应用三步各司其职:setupApp按name存一份默认参数,后面调用不用重复填;preloadApp把资源提前拉下来,exec: true时连代码都先执行完,用户点进来基本秒开;startApp才真正渲染。如果主应用彻底不用某子应用了,用destroyApp销毁——这是破坏性操作,后面坑点里细说。
🚦 子应用要改多少代码?先解决跨域
先给结论:跨域配好之后,保活和重建模式下一个字都不用改子应用;只有单例模式要做生命周期改造(下面单独讲)。
子应用的静态资源和接口请求都是从主应用域名发起的,所以子应用服务器必须开放 CORS。用 Node.js 部署的话,服务端加一段响应头就够了:
app.use((req, res, next) => { res.set({ "Access-Control-Allow-Credentials": true, "Access-Control-Allow-Origin": req.headers.origin || "*", "Access-Control-Allow-Headers": "X-Requested-With,Content-Type", "Access-Control-Allow-Methods": "PUT,POST,GET,DELETE,OPTIONS", }); next(); });这段中间件会把主应用来源回显给浏览器,加载时的"资源请求报错"就消失了;具体放行范围按你的业务收紧。另外,遇到代码根本碰不到的子应用,还可以用replace钩子在运行时改写它的 HTML / JS / CSS,源工程一行不动。
🧭 三种运行模式怎么选
无界把子应用分成三种运行模式,区别在"切换页面时子应用被怎么对待":
| 模式 | 开启方式 | 改造成本 | 适用场景 |
|---|---|---|---|
| 保活模式 | alive: true | 零改造 | 不想白屏、要保留状态;老项目首选 |
| 重建模式 | 不保活、不改造(默认) | 零改造 | 低频子应用、内存敏感场景 |
| 单例模式 | 不保活 + 生命周期改造 | 需改造 | 多个菜单要跳到同一子应用的不同页面 |
白话翻译:保活 ≈ 实例常驻内存,切换只显隐不重建;重建 = 每次进来都推倒重来;单例 ≈ 常驻一个"插槽",切换时销毁旧实例、创建新实例,而且可以靠改url精准定位到新实例的子路由。
一句话选型:子应用碰不了代码,选保活;要省内存且接受重新加载,选重建;多个菜单指向同一子应用的不同页面,选单例(这时把name设成同一个,各菜单还能共享一个实例和承载 JS 的 iframe)。更多细节可看仓库文档 docs/guide/mode.md。
✍️ 单例模式生命周期怎么写
选了单例模式,就要把子应用的"创建、挂载、销毁"包进两个函数:挂在window.__WUJIE_MOUNT,销毁挂在window.__WUJIE_UNMOUNT。以 Vue 3 为例:
if (window.__POWERED_BY_WUJIE__) { let instance; window.__WUJIE_MOUNT = () => { const router = createRouter({ history: createWebHistory(), routes }); instance = createApp(App); instance.use(router); instance.mount("#app"); }; window.__WUJIE_UNMOUNT = () => { instance.unmount(); }; } else { createApp(App).use(createRouter({ history: createWebHistory(), routes })).mount("#app"); }window.__POWERED_BY_WUJIE__是无界注入的标记位,等于"我正被无界接管"。特别注意:Vite 项目因为脚本是异步加载的,实例化时机不确定,定义完上面两个函数后要主动调一次window.__WUJIE.mount(),无界的 mount 函数内置了去重标记,不会重复挂载。
⚠️ 高频坑点,踩过的都在这
- 预加载与启动参数不一致:
name、replace、fetch、alive、degrade这五个参数在preloadApp和startApp里必须严格一致,最常见的事故就是改了预加载配置忘了同步启动配置,渲染直接异常。 - 保活模式下改 url 不跳路由:实例是常驻的,
startApp改变url对路由无效。想让保活子应用换页面,得用bus(无界自带的事件总线,主应用和子应用各持一端)通信跳转。 - 别随手 destroyApp:它会把 iframe、shadowRoot 和无界实例一起销毁,缓存全清。只要子应用后面还会打开,下次进来就会有一段白屏;"重建"用
refreshApp就够了,destroyApp留给真正"再也不用"的场景。 - Vite 子应用里 location 不对:module 脚本无法被代理劫持,
window.location.host拿到的是主应用的 host。要读子应用自己的 host,统一改用$wujie.location.host(无界注入在window.$wujie上)。 - 降级有代价:
degrade: true时子应用跑进真 iframe,理论上能兼容老浏览器,但弹窗困在 iframe 里盖不住整页。只给确认不兼容的浏览器打开,别全局开。
🚀 上线前再看三条进阶建议
- 核心子应用预执行:
preloadApp配合exec: true再加保活,请求和渲染全部提前完成,接近 SSR 的秒开体验。代价是预加载占用网络线程、预执行占用渲染线程,别无脑全开。 - 路由同步 + 短路径:
sync: true会把子应用路由写进主应用 URL 的查询参数,刷新、分享链接都不丢状态;链接太长时用prefix做短路径替换。 - 接口带 cookie:子应用请求需要携带 cookie 时,传一个自定义 fetch 即可:
fetch: (url, options) => window.fetch(url, { ...options, credentials: "include" })。
你的第一步:挑一个最核心的子应用,用"保活模式 + 预加载"在本地跑通(子应用不改代码,只把服务端跨域打开),链路稳定之后再评估要不要升级到单例模式。
【免费下载链接】wujie极致的微前端框架项目地址: https://gitcode.com/gh_mirrors/wu/wujie
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
