微前端方案介绍

微前端的核心价值:

  • 技术栈无关
  • 独立开发、独立部署
  • 增量升级
  • 独立运行时(每个微应用之间状态隔离,运行时状态不共享)

1.iframe

iframe是一个比较传统的微前端技术方案,上手难度低,使用简单。

优点
  1. 天然隔离性
    • 沙箱环境:iframe 自带浏览器级别的 JS/CSS 隔离。
    • 安全限制:遵循同源策略,跨域场景下可限制恶意操作。
  2. 独立运行能力
  3. 技术栈无关性
  4. 低侵入性
    • 无需额外构建工具或框架,接入成本低。
  5. 多页面支持
    • 适合嵌入完整的独立页面(如第三方地图、文档工具)。
缺点
  1. 性能问题
    • 重复加载:每个 iframe 需加载完整的 HTML/JS/CSS,资源无法共享(如公共依赖)。
    • 内存消耗:多个 iframe 会导致内存占用高,可能引发页面卡顿。
    • 通信开销:跨 iframe 通信依赖 postMessage,性能较差。
  2. 用户体验差
    • 布局限制:UI 不同步,DOM 结构不共享(如弹窗问题)。
    • 加载状态:子应用加载无占位,可能显示空白或闪烁。
    • 路由同步:父应用与 iframe 内的路由状态难以同步(如浏览器前进/后退)。
  3. 开发体验问题
    • 调试困难:Chrome 开发者工具需单独切换 iframe 上下文。
    • 构建配置:子应用需单独配置 CSP(内容安全策略)、跨域策略等。
    • 样式隔离过度:父应用无法直接覆盖子应用样式,定制化困难。
  4. SEO 不友好
    • 搜索引擎可能无法抓取 iframe 内的动态内容。
  5. 现代 API 限制
    • 部分浏览器 API(如摄像头、地理位置)在跨域 iframe 中需额外授权。
适用场景
  • 简单嵌入第三方页面(如广告、地图、文档预览)。
  • 短期快速接入,且对性能、体验要求不高的场景。

2.qiankun

qiankun 是一个基于 single-spa 的微前端实现库。阿里系开源的微前端框架,使用人数较多。

特性
  • 📦 基于 single-spa 封装,提供了更加开箱即用的 API。
  • 📱 技术栈无关,任意技术栈的应用均可 使用/接入,不论是 React/Vue/Angular/JQuery 还是其他等框架。
  • 💪 HTML Entry 接入方式,让你接入微应用像使用 iframe 一样简单。
  • 🛡​ 样式隔离,确保微应用之间样式互相不干扰。
  • 🧳 JS 沙箱,确保微应用之间 全局变量/事件 不冲突。
  • ⚡️ 资源预加载,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度。
  • 🔌 umi 插件,提供了 @umijs/plugin-qiankun 供 umi 应用一键切换成微前端架构系统。
缺点
  • 2.x 不支持Vite。如果要使用 vite,可以考虑使用 vite-plugin-qiankun 插件;
  • 3.0加入了支持 vite,不过功能还待完善。

3.Micro-App

Micro App 是京东出的一款基于 Web Component 原生组件进行渲染的微前端框架,不同于目前流行的开源框架,它从组件化的思维实现微前端,旨在降低上手难度、提升工作效率。

4.无界

无界(Wujie)是腾讯开源的微前端框架,主打 ​​轻量、零成本接入​​ 和 ​​极致性能​​,它是一种基于 Web Components + iframe 的全新微前端方案,通过 ​​iframe 的优化实现沙箱隔离​​,同时避免了传统 iframe 的缺点。


5.方案对比

框架核心特性对比
特性QiankunMicro-App无界(Wujie)
底层原理基于 Single-SPA + JS 沙箱Web Components + Proxy 沙箱Web Components + 优化版 iframe
隔离性JS/CSS 沙箱(Proxy/Snapshot)ShadowDOM + JS 沙箱iframe 原生隔离 + CSS 沙箱
接入成本高(需适配生命周期)低(无侵入式接入)极低(零改造接入)
通信方式initGlobalState / propswindow.microApp / eventprops / eventBus
路由同步需配置 activeRule自动同步(可选)自动同步
性能中(沙箱代理开销)高(轻量无代理)高(iframe 优化版)
兼容性IE11 需 Polyfill(Proxy 限制)需 Polyfill(Web Components)支持 IE11+(无 Proxy 依赖)
预加载/缓存支持支持支持(资源复用)
保活模式支持支持支持
社区生态成熟(阿里开源),较长时间没更新中等(京东团队),更新较快较新(腾讯开源),更新较快

6.Web Component

Web Components 允许创建可重用的自定义元素,由三项主要技术组成:

  1. Custom Elements(自定义元素):一组 JavaScript API,允许定义自定义元素及其行为
  2. Shadow DOM(影子 DOM):一组 JavaScript API,用于将封装的"影子"DOM树附加到元素
  3. HTML Templates(HTML模板)<template><slot> 元素可以编写不在呈现页面中显示的标记模板

1.Custom Elements(自定义元素)

自定义元素允许定义自己的 HTML 标签并在页面上使用它们。

1.1 创建自定义元素
class MyElement extends HTMLElement {
  constructor() {
    super();
    // 元素创建时的初始化代码
    this.textContent = 'Hello, Web Components!';
  }
  
  // 定义元素被添加到文档时调用的方法
  connectedCallback() {
    console.log('元素被添加到DOM中');
  }
  
  // 定义元素从文档中移除时调用的方法
  disconnectedCallback() {
    console.log('元素从DOM中移除');
  }
  
  // 定义元素属性变化时调用的方法
  attributeChangedCallback(name, oldValue, newValue) {
    console.log(`属性 ${name}${oldValue} 变为 ${newValue}`);
  }
  
  // 定义需要观察的属性列表
  static get observedAttributes() {
    return ['my-attr'];
  }
}

// 注册自定义元素
customElements.define('my-element', MyElement);
1.2 使用自定义元素
<my-element my-attr="value"></my-element>

2.Shadow DOM(影子 DOM)

Shadow DOM 允许将隐藏的 DOM 树附加到常规 DOM 树中的元素上,实现封装。

2.1 创建带 Shadow DOM 的自定义元素
class ShadowElement extends HTMLElement {
  constructor() {
    super();
    
    // 创建影子DOM
    const shadow = this.attachShadow({mode: 'open'});
    
    // 创建元素
    const wrapper = document.createElement('div');
    wrapper.setAttribute('class', 'wrapper');
    
    const style = document.createElement('style');
    style.textContent = `
      .wrapper {
        color: blue;
        border: 1px solid black;
        padding: 10px;
      }
    `;
    
    shadow.appendChild(style);
    shadow.appendChild(wrapper);
    wrapper.textContent = '这是一个带Shadow DOM的元素';
  }
}

customElements.define('shadow-element', ShadowElement);
2.2 使用 Shadow DOM 元素
<shadow-element></shadow-element>

3.HTML Templates(HTML模板)

HTML 模板允许定义可重用的 HTML 结构,这些结构在页面加载时不会被渲染,但可以在运行时实例化。

3.1 使用模板
<template id="my-template">
  <style>
    .card {
      border: 1px solid #ccc;
      border-radius: 5px;
      padding: 10px;
      margin: 10px;
      width: 200px;
    }
    .title {
      font-weight: bold;
      margin-bottom: 5px;
    }
  </style>
  <div class="card">
    <div class="title"><slot name="title">默认标题</slot></div>
    <div class="content"><slot name="content">默认内容</slot></div>
  </div>
</template>
3.2 在自定义元素中使用模板
class TemplateElement extends HTMLElement {
  constructor() {
    super();
    
    const shadow = this.attachShadow({mode: 'open'});
    const template = document.getElementById('my-template');
    const instance = template.content.cloneNode(true);
    shadow.appendChild(instance);
  }
}

customElements.define('template-element', TemplateElement);
3.3 使用带插槽的元素
<template-element>
  <span slot="title">自定义标题</span>
  <span slot="content">这是自定义内容</span>
</template-element>

工具和库

虽然 Web Components 是原生技术,但有些库可以简化开发:

  • ​​Lit​​ - Google开发的轻量级库,简化Web Components开发
  • Stencil​​ - 用于构建可重用Web Components的编译器
  • ​​Svelte​​ - 可以编译为Web Components的框架

7.Module Federation

Webpack 5 引入了 Module Federation(模块联邦),它允许在多个独立构建的应用或微前端之间共享代码和依赖。

核心概念

  • ​​跨应用共享模块​​:不同应用可以共享库、组件或任何模块
  • ​​​​运行时动态加载​​:无需在构建时将所有代码打包在一起
  • ​​​​独立部署​​:每个应用可以独立开发、构建和部署
  • ​​​​版本控制​​:可以指定共享模块的版本要求

使用场景

  • 微前端架构​​:多个团队独立开发的前端应用可以共享组件和状态
  • 大型应用拆分​​:将巨型应用拆分为多个可独立部署的小应用
  • ​​​​第三方组件库​​:跨项目共享UI组件而不需要发布到npm
  • 渐进式迁移​​:逐步将旧系统迁移到新技术栈

8.qiankun 原理

核心实现原理可以概括为以下几个关键点:

1. 应用加载机制

Qiankun 通过以下方式加载子应用:

  1. HTML Entry:不同于 JS Entry,Qiankun 通过解析子应用的 HTML 文件来获取静态资源和入口脚本
  2. 资源加载:使用 import-html-entry 库来加载子应用的 HTML,解析其中的 JS/CSS 资源
  3. 沙箱执行:在隔离环境中执行子应用的 JavaScript 代码

2. JS 沙箱隔离

Qiankun 实现了三种沙箱机制来隔离子应用的 JavaScript 执行环境,并会根据环境选择对应的沙箱机制:

  1. SnapshotSandbox(快照沙箱):
    • 在应用挂载时保存全局状态快照
    • 应用卸载时恢复快照
    • 适用于单实例场景

缺点: 遍历 window 上所有属性,性能差;同一时间只能激活一个微应用。
优点: 可以支持不兼容 Proxy 的浏览器。

  1. LegacySandbox(传统沙箱/单实例沙箱):
    • 基于 Proxy 实现
    • 记录应用运行时对 window 的修改
    • 应用卸载时恢复这些修改

缺点: 同一时间只能运行一个应用;兼容性没有快照沙箱好。
优点: 不需要遍历 window 上的所有属性,性能比快照沙箱要好。

  1. ProxySandbox(多实例沙箱):
    • 每个子应用都有独立的沙箱环境
    • 通过 Proxy 拦截对 window 的访问和修改。主要实现在 constructor 中,创建一个 fakeWindow 对象,通过 Proxy 代理这个对象,全程没有改变 window
    • 支持多实例同时运行

缺点: 兼容性没有快照沙箱好。
优点: 没有污染全局 window;支持多实例;性能好;

沙箱的选择机制:
判断浏览器环境是否支持 Proxy,不支持则选择快照沙箱,支持则选择单、多例沙箱。再​​根据配置和场景选择单、多例沙箱。

3. CSS 样式隔离

Qiankun 提供了两种样式隔离方案:

  1. Shadow DOM

    • 将子应用挂载到 Shadow DOM 中
    • 实现天然的样式隔离
  2. Scoped CSS

    • 动态添加/移除 <style> 标签
    • 应用卸载时移除对应的样式
  3. 动态样式表

    • 卸载子应用时移除其样式表,重新挂载时恢复
    • 有全局污染风险

选择机制:
默认使用动态样式表;若配置 strictStyleIsolation 为 true,则使用 Shadow DOM 方案;若配置 experimentalStyleIsolation,则使用 ​​Scoped CSS 方案。

4. 应用间通信

Qiankun 提供了以下通信方式:

  1. 全局状态管理

    • 通过 initGlobalState 初始化全局状态
    • 子应用通过 onGlobalStateChange 监听状态变化
    • 通过 setGlobalState 修改状态
  2. 自定义事件

    • 基于浏览器原生 CustomEvent 实现
    • 主应用和子应用可以通过事件进行通信

5. 子应用生命周期

Qiankun 管理子应用的生命周期,包括:

  1. bootstrap:应用初始化时调用
  2. mount:应用挂载时调用
  3. unmount:应用卸载时调用
  4. update:应用更新时调用(可选)

6. 路由劫持

Qiankun 通过重写 window.history 的相关方法(pushState/replaceState)来实现路由劫持,确保主应用能够正确捕获路由变化并加载对应的子应用。

实现流程示例

  1. 主应用注册子应用配置
  2. 用户访问特定路由时,主应用匹配到对应的子应用
  3. 加载子应用的 HTML 入口文件
  4. 解析 HTML 获取 JS/CSS 资源
  5. 创建沙箱环境
  6. 在沙箱中执行子应用的 JS 代码
  7. 将子应用挂载到指定的 DOM 容器
  8. 监听路由变化,在需要时卸载/加载子应用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值