想象一下,你们公司有一栋“巨型写字楼”,所有业务团队都挤在同一层楼里办公。几百人在开放式工位里敲代码、改系统,一个团队上线新功能,整层楼都要停机维护;一个团队改了全局样式,其他团队的页面瞬间崩掉——这就是单体前端应用的日常噩梦。为了让大团队像小团队一样独立作战,前端界催生了「微前端」理念,而落地它最主流的两种方案,就是 qiankun 和 Module Federation。 qiankun 像一位“物业大管家”:它把写字楼划成独立商铺,统一搞定水电、门禁和装修隔离,子应用随时入驻、随时搬走。Module Federation 则更像“中央共享仓库”:每个团队各自建楼独立运营,但所有楼群共享一个公共资源库,谁缺组件、缺依赖,都能从仓库里实时取用。两种路线、两套哲学,谁更适合你的团队,正是这篇文章要解决的问题。 学完这篇,你将能分清 qiankun 和 Module Federation 的技术路线差异,在面试和架构评审中自信地给出微前端选型建议——这是中高级前端工程师和前端架构师的核心能力。
需要学习微前端(qiankun/Module Federation),扎实的编程功底是AI应用开发的基础。本篇涵盖Python、Git、Docker、IDE与开发工具链,帮助你掌握工程化开发能力。
可视化演示
展示两种主流微前端方案:qiankun基于路由劫持和JS沙箱的子应用隔离、Module Federation基于Webpack5的模块共享与运行时注入、以及五维度横向对比。交互切换架构视图。
本节配有交互动效(进入视口后自动加载,约 3KB)。
qiankun微前端架构 主应用→路由劫持→JS沙箱→子应用加载 沙箱隔离子应用全局变量防止污染 loadApp(entry, { sandbox: true }) qiankun通过HTML entry+JS沙箱实现子应用隔离
微前端概述
想象一家搬到新办公楼的科技公司。最初大家挤在同一个大平层,工位之间没有任何隔断,市场部改个海报,全楼都要一起换装修;研发部升级服务器,整层楼的 WiFi 都要断掉。公司决定按业务线重新划分空间,让每个团队拥有自己的独立办公区——这个“拆分再组合”的思路,就是微前端。
微前端不是某个框架,而是一种架构思想:把大型前端应用按业务边界拆成多个可独立开发、独立部署的子应用,再通过某种机制把它们组合成一个对用户来说完整统一的产品。它与后端微服务的理念同源,只不过切分的是浏览器里那些会互相踩脚趾的 JS 和 CSS。拆完之后,两个团队再也不用因为同一个仓库的合并冲突而互相等待。
业界落地微前端有两条主流路线。qiankun 走的是“物业式管控”:一个主应用当“壳”,负责把各个子应用装进自己的页面容器里,并提供沙箱、样式隔离等基础能力。Module Federation 走的是“仓库式共享”:它基于 Webpack5,让多个应用不仅各自独立运行,还能在运行时互相加载对方的模块,实现真正意义上的资源共享。
回到大楼的比喻:无论是请物业统一管理,还是建公共仓库共享资源,最终目的都是让这栋楼从“一锅粥”变成“井然有序的园区”。微前端要解决的就是组织协作问题,而不是单纯的技术炫技。
- 拆分重组把大型前端拆成多个独立的业务单元。每一个 $f_i$ 单独开发、单独上线,谁也不挡谁的路,就像把大平层改造成一间间独立办公室。
- 独立部署每个子应用拥有自己的代码仓库和发布流程,一个团队发版不需要拉上全楼的人一起熬夜。
- 组合机制用 qiankun 或 Module Federation 把散装的子应用重新拼成一个完整产品,用户无感知。
qiankun核心原理
访客走进一栋由物业管理的写字楼,第一步不是直接冲向楼层,而是先到前台。前台根据访客要找的人(路径),查看登记表(激活规则),然后告诉访客该去几楼几号房。qiankun 的主应用就是那个“前台”,子应用就是楼里的各个公司。
qiankun 基于 single-spa 这类微前端基座库发展而来。它通过监听浏览器地址栏的变化,在路由切换时动态决定应该由哪个子应用来接管页面的渲染。当用户访问 /order/list 时,主应用发现这个路径属于“订单应用”,于是把订单应用加载到指定的 DOM 容器中,挂载展示;当用户离开这个路径,再把它卸载清理。这一切都在运行时发生,不需要重新构建主应用。
qiankun 有两个核心设计。第一是路由劫持:它重写了 window.history 和 hashchange 事件,让路由变化时能通知所有已注册的子应用去判断自己是否该激活。第二是 HTML entry:与传统的 JS entry 不同,qiankun 允许子应用直接暴露一个 HTML 文件地址,主应用像浏览器一样去 fetch 这个 HTML,然后解析出里面的 JS 和 CSS 再执行——这意味着子应用可以用任何技术栈开发,Vue、React、Angular、甚至原生 JS 都能接入。
物业前台的比喻在这里非常贴切:qiankun 的重担就是“正确地引导访客”,而这依赖一张清晰的登记表(路由规则)。一旦登记表混乱,访客就会走错楼层——这也是微前端架构中最常见的翻车现场。
- 路径状态浏览器地址栏中的 pathname 是路由分发的唯一依据,比如
/order/list。 - 激活规则每个子应用注册时声明自己负责的路由前缀,像公司在前台登记的楼层信息。
- 匹配判定主应用调用字符串前缀匹配,判断当前路径是否属于某个子应用。
JS沙箱机制
物业为了防止租户之间互相干扰,给每个商铺装上了独立电表和门禁系统。租户在自己屋里开多少空调、装多少电器都行,但电费只走自己的表;租户退租时,物业把屋子恢复到初始状态,下一位租户进来时看到的还是那间干净的空房。qiankun 的 JS 沙箱做的就是这件事。
子应用运行时会往全局对象 window 上挂载各种变量、设置定时器、绑定事件监听器。如果不做隔离,子应用 A 卸载后,它在 window 上留下的全局变量会继续存在,可能覆盖子应用 B 的同名变量,导致数据错乱甚至白屏。qiankun 提供了快照沙箱和代理沙箱两种主流方案来解决这个问题。
快照沙箱的原理很朴素:子应用激活前,把 window 上所有属性复制一份快照;子应用运行期间随意修改;卸载时,遍历快照把所有属性恢复原状。代理沙箱则更优雅:它利用 ES6 的 Proxy 给 window 套了一层拦截器,子应用读取某个属性时先查虚拟环境,查不到再找真实 window;写属性时只写入虚拟对象,真实 window 完全不被触碰。代理沙箱性能更好,也是 qiankun 默认推荐的方式。
电表不会因为楼上租户多开了一台空调而跟着跳闸,代理沙箱也不会因为子应用 A 写了几个全局变量而影响子应用 B 的运行。沙箱是微前端信心的基石,但记住它只负责 JS 的隔离,CSS 的隔离还得靠下一节的招数。
- 代理封装用 Proxy 把真实的 window 对象包裹起来,返回一个新对象给子应用使用。
- 读取拦截子应用读属性时,代理先查虚拟环境,找不到才回退到真实 window。
- 写入拦截子应用写属性时,代理把值存在虚拟对象里,真实 window 完全不被污染。
样式隔离方案
商场物业对每间店铺的装修有一条硬性规定:店铺招牌必须带商场统一的编号前缀,比如 A-301、B-205。这样即使两家店都卖奶茶,顾客也不会走错门。CSS 样式隔离的思路也是如此——给每个子应用的样式起一个“带编号的名字”。
子应用的 CSS 默认是全局的,如果子应用 A 写了 .btn { background: red },子应用 B 也写了 .btn { background: blue },后加载的样式会覆盖先加载的,页面颜色就乱了。qiankun 提供了三种层次的样式隔离手段。最彻底的是 Shadow DOM 严格隔离:把子应用的 DOM 放进一个 shadowRoot 里,浏览器天然保证内外样式互不可见,但这种方案对弹窗、浮层等挂载到 body 下的元素无能为力。
第二层是实验性样式隔离:qiankun 在运行时扫描子应用加载的样式表,给每个选择器加上一个带应用名前缀的属性选择器,比如 .btn 变成 .order-app .btn,这样即使两个应用都有 .btn,作用域也不同。第三层则是团队约定:大家约好每个类名都带命名空间,比如 .order-btn、.user-avatar,用代码规范代替运行时开销。这三种方案可以组合使用,实际项目中最常见的是“实验性隔离 + 命名约定”双保险。
装修再美观,招牌编号乱了也会让人走错门。样式隔离不一定需要做到 100% 物理隔离,能让两个团队在各自的“命名空间”里安心写样式,就已经解决了 90% 的冲突问题。
- 原始样式子应用开发者写的标准 CSS 规则,比如
.btn { color: red }。 - 命名空间映射给所有选择器加上应用名作为前缀,避免全局冲突。
- 作用域落地改写后的样式只在子应用自己的容器内生效,不会泄漏到别的应用。
模块联邦原理
如果说 qiankun 是请物业来管楼,Module Federation 就是干脆让每个团队自己建楼,然后在园区中心修一座“中央共享仓库”。市场部需要一套模板组件,不用自己造轮子,直接从仓库里拿;研发部升级了共享工具库,所有楼群第二天自动用上新版本。
Module Federation 是 Webpack5 内置的模块共享能力。它在构建阶段通过 ModuleFederationPlugin 插件声明两件小事:本应用要“暴露”哪些模块给别人(exposes),以及本应用要“借用”哪些共享依赖(shared)。构建完成后,每个应用还是一个独立的可部署产物,但产物里多了一份“远程模块的引用地图”,真正加载远端模块发生在浏览器运行时。
模块联邦解决的是“运行时依赖注入”问题:应用 A 的代码里可以 import('appB/Button'),构建时 Webpack 不打包这份代码,而是生成一个运行时加载函数;当浏览器执行到这行代码时,才去应用 B 的服务器上请求 Button 模块。同时,shared 机制还能让多个应用共享同一个 React 实例,避免重复加载导致的状态不同步。这种“用的时候才去拿”的方式,比把所有公共代码打进每个应用的包里高效得多。
中央仓库的意义在于“人人可共享、处处不重复”。但仓库也需要管理规则:谁负责维护共享包的质量?版本升级如何通知所有群租楼?这些问题在部署与版本管理部分会进一步展开。
- 暴露模块应用通过 exposes 字段描述哪些模块可以被其他应用远程加载。
- 共享依赖通过 shared 字段声明哪些公共依赖希望全局只有一份,如 react、vue。
- 运行时解析构建产物中只有 remote 的引用地址,执行时才通过 jsonp 加载远端模块。
通信机制设计
大楼里的商户之间免不了要传递消息:奶茶店要向会员中心确认顾客的积分,商场广播要通知所有店铺新的促销活动。微前端里的子应用通信,就是设计一套清晰的“传话系统”,让消息不靠吼,而是走正规渠道。
qiankun 和 Module Federation 都支持多种通信方式,团队可以根据耦合程度选择。第一种是 props 透传:主应用在挂载子应用时,把需要的数据和方法作为 props 传进去。这像物业在店铺开业时递上一本《商户手册》——一次性给到位。第二种是全局状态管理:在主应用中维护一个全局状态容器(比如 Redux 或 Zustand),子应用通过订阅状态变化来响应更新,适合跨应用共享登录态、用户信息等高频数据。第三种是自定义事件:通过浏览器的 window.dispatchEvent 和 addEventListener 实现事件广播,最适合松耦合的“通知型”通信,比如“订单已创建,请刷新列表”。
通信设计最怕的是“没有约定”。如果所有子应用都直接 import 一个全局单例对象,改动时牵一发动全身,耦合度比单体应用还高。所以微前端的最佳实践是把通信协议文档化:哪些数据用 props 注入、哪些状态进全局 store、哪些消息走事件总线,都事先约定清楚。
回到商场比喻:传话系统越规范,商户之间的协作越顺畅。无论是物业手册(props)还是商场广播(事件),关键是让每个商户知道“该听谁的广播、该按哪本手册办事”,而不是遇到问题就伸长脖子喊一嗓子。
- 动作产生用户操作或业务事件产生一个标准消息对象,比如
{ type: 'LOGIN', payload: user }。 - 状态流转reducer 根据旧状态和 action 计算新状态,这是 Redux 等全局状态库的通用模型。
- 订阅通知其他子应用订阅状态变化后自动刷新界面,完成跨应用联动。
部署差异对比
请物业管理的商场和各自建楼的产业园,在“盖房子”这件事上的流程完全不同。商场是统一规划、分店铺装修;产业园是各家独立施工、再修路连通。qiankun 和 Module Federation 的部署差异,恰好也具有这种结构性的不同。
qiankun 的部署模式是“一个壳 + 多个独立子应用”。主应用和各子应用分别构建、分别部署到不同的静态服务器或 CDN 路径上。主应用通过配置的子应用 HTML 地址去加载它们,所以子应用发版完全不需要主应用重新构建——这非常适合多团队并行发布的场景。版本管理也简单:每个子应用的 URL 就是它的版本号,切换版本只需更新主应用的注册配置。
Module Federation 的部署模式则更接近“统一构建生态”。虽然每个应用也是独立部署,但由于存在运行时互相加载的依赖关系,远端模块一旦发布新版本,所有引用它的宿主应用在下次访问时会自动拿到新代码。好处是模块复用极高效,风险是版本失控:一个远端应用发布了一个破坏性变更,可能让所有宿主应用同时报错。因此 MF 的版本管理必须更精细,常见的策略是 shared 依赖制定版本范围,并结合构建时的 requiredVersion 校验。
商场有商场的规范,产业园有产业园的自由。qiankun 的部署模式对运维友好、故障隔离直观;MF 的部署模式对共享高效、但需要更强的工程治理能力。选择哪种,取决于你们团队能不能驾驭“自由的代价”。
- 版本约束每个共享依赖声明它所需的版本区间,像租户在仓库借货时写明“需要 18.x 以上的规格”。
- 宿主版本运行时检查宿主提供的实际版本号是否落在这个区间内。
- 兼容结论满足区间则共享,否则返回 0 并自动 fallback 到加载自己的副本。
选型实践指南
面对物业和中央仓库两种方案,决策者不该拍脑袋,而要像技术委员会一样系统地评估三个维度:团队规模、技术栈匹配、共享需求强度。
如果团队规模大、技术栈杂、业务系统多,需要清晰的“壳 + 子应用”边界来治理,qiankun 是更稳妥的选择。它接入成本低,对已有系统的侵入性小,子应用可以用任何框架改造,甚至老旧的 jQuery 项目也能慢慢迁移进来。如果团队规模小、技术栈统一、多个应用之间有大量需要复用的业务组件和公共依赖,Module Federation 会更顺手——它把共享写进了构建工具里,不用像 qiankun 那样在运行时做层层包裹。
技术栈匹配也很关键:项目还在用 Webpack4,迁移到 MF 需要先升级 Webpack5,工作量大;而 qiankun 对构建工具没要求。反过来,如果团队本来就在 Webpack5 上,而且痛点不是“应用隔离”而是“模块复用”,那 MF 的优势就非常明显。最后是治理能力:MF 的运行时共享虽然灵活,但版本失控和循环依赖风险都需要强大的工程规范来兜底;qiankun 的沙箱和样式隔离则更像“强制纪律”,天然约束了子应用的越界行为。
选物业还是建仓库,没有标准答案,只有“最适合你们园区现状”的答案。更聪明的做法是认识到两者并不对立:qiankun 可以装入用 MF 构建的子应用,两种方案可以组合使用,让物业管隔离、仓库管共享。
- 团队评估考察团队人数、技术栈分布和协作模式,人多且杂时更倾向 qiankun 的强隔离。
- 架构评估评估现有构建链路和部署环境,Webpack5 生态下 MF 的接入成本更低。
- 治理评估评估代码仓库归属和发布节奏,高频发版且模块共享多的团队更适合 MF。
- 综合决策把三个维度代入决策函数,得到一个适合自身场景的答案。
AI 应用场景
AI 中台的多团队前端协作
阶段:模型服务的可视化交付
解决的问题:AI 团队内部通常有算法组、平台组、标注组并行开发,各组的技术栈和发布节奏不同。传统的单体前端需要所有组协商一个发布窗口,改动频繁的算法可视化界面往往被平台组的版本节奏拖住。
具体案例:某 AI 公司的模型训练平台采用 qiankun 重构,把“数据集管理”“模型训练监控”“评估报告”拆成三个子应用。算法组用 React 维护训练监控,平台组用 Vue 维护数据管理,标注组甚至用原生 JS 做了一个快速标注工具。主应用统一提供导航和权限,子应用各自发版,原本两周一次的联调变成了各团队随时独立上线。
AI 可视化平台的模块联邦共享
阶段:模型的在线推理与结果展示
解决的问题:同一个 AI 团队维护多个面向不同业务线的可视化产品,每个产品都需要“模型结构图”“推理耗时曲线”“样本分布散点图”等通用组件。如果每个应用各写一份,组件 bug 要改多处;如果抽成 npm 包,每次发版都要全量升级。
具体案例:团队用 Module Federation 搭建了一个“可视化组件仓库”,公共组件仓库在共享中心统一维护,多个 AI 应用通过 exposes 和 shared 在运行时动态加载相同的组件实例。当工程师修复了散点图中的一处渲染 bug,所有应用在下次访问时自动拿到修复版本,不需要任何额外部署。
Python 演示
"""模拟微前端两种方案:qiankun 的沙箱隔离与 Module Federation 的共享模块。""" class App: """一个微前端子应用,模拟注册时的基本信息。""" def __init__(self, name, active_rule): self.name = name self.active_rule = active_rule def match(self, path): """判断当前路由是否命中本应用。""" return path.startswith(self.active_rule) class QiankunSandbox: """模拟 qiankun 快照沙箱:激活时记录,卸载时还原。""" def __init__(self, window_env): self.window_env = window_env self.snapshot = {} self.modified_keys = set() def grant(self): self.snapshot = dict(self.window_env) def set_attr(self, key, value): self.window_env[key] = value self.modified_keys.add(key) def revoke(self): for key in self.modified_keys: if key in self.snapshot: self.window_env[key] = self.snapshot[key] else: del self.window_env[key] self.modified_keys.clear() class ModuleFederationRegistry: """模拟 Module Federation 的共享模块池。""" def __init__(self): self.module_pool = {} def get_or_create(self, module_name, version, factory): pool_key = (module_name, version) if pool_key not in self.module_pool: self.module_pool[pool_key] = factory() return self.module_pool[pool_key] def main(): # qiankun 场景:子应用运行期间修改全局变量,卸载后还原 window_env = {"currentTheme": "light"} sandbox = QiankunSandbox(window_env) sandbox.grant() sandbox.set_attr("currentTheme", "dark") print("子应用运行期间:", window_env) sandbox.revoke() print("子应用卸载后还原:", window_env) # Module Federation 场景:多个应用共享同一个模块实例 registry = ModuleFederationRegistry() react_a = registry.get_or_create("react", "18.2.0", lambda: {"name": "react"}) react_b = registry.get_or_create("react", "18.2.0", lambda: {"name": "duplicate"}) print("两个应用拿到同一份 React?:", react_a is react_b) if __name__ == "__main__": main()
def match(self, path):每个子应用声明自己的路由激活规则,类似物业前台查登记表决定访客去向。self.snapshot = dict(self.window_env)子应用启动前给 window 拍快照,记录修改前的原始状态。self.window_env[key] = value子应用运行期间可以修改全局对象,模拟真实业务的全局变量写入。if key in self.snapshot: self.window_env[key] = self.snapshot[key]卸载时用快照还原,清理子应用的全局污染。pool_key = (module_name, version)MF 按“名字 + 版本”作为共享模块的键,避免不同版本的模块互相覆盖。if pool_key not in self.module_pool:命中共享则直接复用,不命中才执行 factory 创建新实例,这就是单例共享的原理。
常见误区
误区很多人第一次听说微前端就想到 iframe,以为 qiankun 只是把子应用塞进 iframe 里的高级封装。反正子应用都是独立页面,用 iframe 不也能隔离吗?
正解qiankun 与 iframe 有本质区别。iframe 是浏览器级别的页面隔离,虽然隔离彻底,但带来了致命问题:路由不同步、弹窗无法跨域、应用间通信极其别扭、性能开销大、而且无法共享浏览器原生能力。qiankun 则是基于 single-spa 的框架级方案,子应用和主应用在同一个文档流中渲染,路由共享地址栏,通过沙箱和样式隔离来模拟“隔离”,兼顾了隔离性和体验。
为何常见:因为 iframe 是前端世界里最直观的“页面套页面”方案,很多人会自然地把它和微前端划等号。
误区以为用了 MF 的 shared 配置后,所有应用加载的 React 或 Vue 都是同一个单例,绝不会出现状态不同步的问题。
正解MF 的共享语义是“尽力而为”。只有当两个应用声明的 shared 版本区间完全匹配时,Webpack 才会复用同一个实例;如果版本范围不兼容,Webpack 会静默地各自加载自己的副本。要让共享真正生效,必须显式配置 singleton: true 并保证各应用的依赖版本在指定范围内,否则就只是“看起来共享了”。
为何常见:因为官方文档强调“共享依赖”,初学者容易把理想情况当成默认行为。
误区以为有了 qiankun 的代理沙箱,子应用无论怎么写全局变量、开多少定时器、绑多少事件监听,都绝对不会影响其他子应用。
正解沙箱只能隔离对 window 对象的属性读写,但拦不住所有副作用。比如子应用修改了 document.title、操作了 localStorage、或者往 body 上挂 DOM 节点,这些属于沙箱管不到的“外部状态”。qiankun 提供了 getMicroAppStateActions 等辅助,但真正的副作用清理还要靠子应用在 unmount 生命周期里手动清理定时器和事件。
为何常见:开发者容易把“沙箱”理解成浏览器级的安全边界,而它实际只是一层 JS 层面的拦截代理。
误区很多团队迁移到微前端是冲着“各团队独立发版”去的,以为只要拆了应用就能彻底摆脱发布节奏的束缚。
正解并行发布是有条件的。qiankun 模式下子应用确实可以独立部署,但主应用的路由配置变化仍需要主应用发版;Module Federation 模式下,远端模块一旦破坏性升级,所有引用它的宿主应用都会受影响。真正的并行发布要求团队同时具备版本兼容意识、接口契约测试和灰度发布能力,微前端只是提供了可能,而不是自动兑现。
为何常见:因为微前端的宣传语往往强调“独立部署”,让人忽略了它是团队协作模式的革命,而不只是技术架构的革命。
误区把两种方案看成非此即彼的竞争对手,做选型时必须在两颗“银弹”里挑一颗。
正解两者解决的问题维度不同。qiankun 解决的是“应用隔离与统一壳管理”,Module Federation 解决的是“模块共享与运行时依赖注入”。在实际项目中完全可以组合使用:用 qiankun 搭建微前端壳,整体管理各个子应用的挂载与隔离;在内部再用 MF 让几个关联密切的子应用共享通用组件和依赖。许多大型中后台系统正是这样混合落地的。
为何常见:因为技术文章倾向于把框架对比着写,容易让读者形成“有你无我”的认知惯性。
面试题
Q1. qiankun 的 JS 沙箱核心作用是以下哪项?
- A.为子应用加速加载性能
- B.隔离全局 window 对象污染← 正确答案
- C.将子应用打包为独立文件
- D.让子应用样式自动加前缀
答案:B。JS 沙箱的核心目的是隔离子应用对 window 全局对象的读写,避免变量互相覆盖。加速加载、打包、样式前缀都不是沙箱的职责,所以 A、C、D 都是干扰项。沙箱就像电表,只管隔离环境,不管省电。
Q2. qiankun 是基于以下哪个库实现的?
- A.Webpack
- B.single-spa← 正确答案
- C.Redux
- D.Express
答案:B。qiankun 基于 single-spa 这个微前端基座库扩展而来,继承了它的应用注册和生命周期管理能力。Webpack 是构建工具,Redux 是状态管理,Express 是后端框架,都与 qiankun 的底基无关。
Q3. qiankun 的 HTML entry 加载方式最突出的优点是?
- A.子应用可用任意技术栈开发← 正确答案
- B.子应用必须使用 Webpack 构建
- C.子应用不需要提供任何入口
- D.子应用和主应用必须同框架
答案:A。HTML entry 意味着主应用直接 fetch 子应用的 HTML 文件,再解析出其中引用的 JS 和 CSS。这种方式完全不关心子应用用什么框架、什么构建工具,因此技术栈完全解耦。B、C、D 都是对 HTML entry 的错误理解。
Q4. 以下关于 Module Federation 的说法正确的有?
- A.它基于 Webpack5 实现← 正确答案
- B.只有主应用能共享模块
- C.应用可同时是宿主和远端← 正确答案
- D.它不需要修改构建配置
答案:AC。MF 是 Webpack5 的原生能力,需要通过 ModuleFederationPlugin 配置 exposes 和 shared。任何应用都可以既暴露模块给他人用(作为 remote),又加载别人的模块(作为 host),所以 C 正确。B 和 D 与 MF 的设计相悖。
Q5. 快照沙箱在子应用退出时如何处理 window?
- A.保留子应用的全部修改
- B.用快照将 window 还原← 正确答案
- C.删除 window 的所有属性
- D.重新创建一个全新的 window
答案:B。快照沙箱的思路是“记录-修改-还原”:启动时拍快照,运行时随意改,退出时用快照覆盖所有修改。它不是删除全部属性(会误伤主应用),也不是重建 window(不可能做到),所以只能选 B。
Q6. qiankun 支持的样式隔离方案包括哪些?
- A.Shadow DOM 严格隔离← 正确答案
- B.实验性样式隔离← 正确答案
- C.CSS 命名空间约定← 正确答案
- D.自动删除全部全局样式
答案:ABC。qiankun 提供了 Shadow DOM 严格隔离、运行时加前缀的实验性隔离,同时社区也普遍采用 CSS 命名空间约定作为低成本方案。D 不是一个合理的方案,删除全局样式会导致页面直接失去基础样式。
Q7. 在 Module Federation 的共享版本冲突中,下列哪种做法最合理?
- A.强制所有应用锁定相同版本
- B.通过 shared 策略设置版本区间校验← 正确答案
- C.完全禁止共享任何第三方依赖
- D.只允许单向依赖注入共享
答案:B。MF 的 shared 配置可以指定版本的 requiredVersion 区间,运行时自动校验宿主版本是否满足要求,不满足则 fallback 到各自副本。强制锁版本和禁止共享都牺牲了灵活性,单向依赖则违背了 MF 的设计初衷,所以 B 最合理。
Q8. 关于 props 透传,下列描述最准确的是?
- A.父应用在挂载子应用时传递数据与方法← 正确答案
- B.子应用主动向父应用拉取所有数据
- C.父应用通过 URL 参数序列化传递数据
- D.子应用之间直接相互访问内存对象
答案:A。props 透传是主应用在子应用 mount 时,把初始化数据和方法作为参数传进去,像物业给新商户递服务手册。它不是子应用主动拉取(那是订阅模型),不是 URL 参数(长度受限且无法传函数),更不是内存直访(违反隔离原则)。
Q9. 微前端最核心的目标是什么?
- A.让所有页面加载速度更快
- B.把大型应用拆成可独立开发部署的单元← 正确答案
- C.彻底消除模块之间的所有依赖
- D.替代后端的微服务架构
答案:B。微前端解决的是大型前端应用的组织协作问题,核心目标是让团队能独立开发、独立部署自己的业务单元。速度提升是可能的副产品,但不是目标;消除所有依赖在现实中不可能;微前端和微服务是两个层面的东西。
Q10. 微前端选型时需要综合考虑哪些因素?
- A.团队规模与协作模式← 正确答案
- B.现有技术栈匹配程度← 正确答案
- C.模块共享需求强度← 正确答案
- D.单个页面按钮点击数量
答案:ABC。选型应围绕团队规模(人多则 qiankun 强治理)、技术栈(Webpack5 生态适合 MF)、共享需求(模块复用强烈则 MF 优势大)三个维度展开。页面按钮点击数量属于产品交互细节,与架构选型无直接关系。