夜猫子的知识栈 夜猫子的知识栈
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

夜猫子

前端练习生
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 微前端

    • 微前端
      • 什么是微前端
      • 关于 Iframe
      • 各大框架
        • QianKun
        • wujie
        • Micro App
      • 其他
        • 联邦模块
        • 微前端实践
  • 权限控制

  • monorepo

  • 《前端架构》
  • 微前端
夜猫子
2024-06-18
目录

微前端

# 什么是微前端

微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。

微前端架构特点:

  • 无关技术栈
  • 开发、仓库、部署独立
  • 允许增量升级、渐进式重构
  • 微应用之间状态隔离,运行时状态不共享

# 关于 Iframe

如果不考虑体验问题,iframe 几乎是最完美的微前端解决方案了。

iframe 最大的特性就是提供了浏览器原生的硬隔离方案,不论是样式隔离、js 隔离这类问题统统都能被完美解决。但他的最大问题也在于他的隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题。

  1. url 不同步,浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用。
  2. dom 结构不共享,想象一下屏幕右下角 1/4 的 iframe 里来一个带遮罩层的弹框,同时我们要求这个弹框要浏览器居中显示,还要浏览器 resize 时自动居中..
  3. 全局上下文完全隔离,内存变量不共享。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果。
  4. 慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。

更多关于微前端的相关介绍,推荐大家可以去看这几篇文章:

  • Micro Frontends (opens new window)
  • Micro Frontends from martinfowler.com (opens new window)

# 各大框架

# QianKun

QianKun (opens new window) 基于 single-spa ,阿里系开源的微前端框架,应该也是大家接触最多的了,社区比较活跃,这点比较重要。

# 实现方案

  • single-spa是基于js-entry方案,而qiankun 是基于html-entry 及沙箱设计,使得微应用的接入像使用 iframe 一样简单。

  • 主应用监听路由,加载对应子应用的html,挂载到主应用的元素内,然后解析子应用的html,从中分析出css、js再去沙盒化后加载执行,最终将子应用的内容渲染出来。

  • qiankun实现样式隔离有两种模式可供开发者选择:

    • trictStyleIsolation:这种模式下 qiankun 会为每个微应用的容器包裹上一个 shadow dom 节点,从而确保微应用的样式不会对全局造成影响
    • experimentalStyleIsolation: 当 experimentalStyleIsolation 被设置为 true 时,qiankun 会改写子应用所添加的样式,会为所有样式规则增加一个特殊的选择器规则,来限定其影响范围
  • qiankun实现js隔离,采用了两种沙箱,分别为基于Proxy实现的沙箱和快照沙箱,当浏览器不支持Proxy会降级为快照沙箱

Proxy沙箱机制:

// 伪代码
class ProxySandbox {
    constructor() {
        const rawWindow = window;
        const fakeWindow = {}
        const proxy = new Proxy(fakeWindow, {
            set(target, p, value) {
                target[p] = value;
                return true
            },
            get(target, p) {
                return target[p] || rawWindow[p];
            }
        });
        this.proxy = proxy
    }
}
let sandbox1 = new ProxySandbox();
let sandbox2 = new ProxySandbox();
window.a = 1;
// 伪代码
((window) => {
    window.a = 'hello';
    console.log(window.a) // hello
})(sandbox1.proxy);
((window) => {
    window.a = 'world';
    console.log(window.a) // world
})(sandbox2.proxy);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

快照沙箱:

// 伪代码
class SnapshotSandbox {
    constructor() {
        this.proxy = window; 
        this.modifyPropsMap = {}; // 修改了那些属性
        this.active(); // 调用active保存主应用window快照
    }

    /**1. 初始化时,在子应用即将mount前,先调用active,保存当前主应用的window快照*/
    active() {
        this.windowSnapshot = {}; // window对象的快照
        for (const prop in window) {
            if (window.hasOwnProperty(prop)) {
                // 将window上的属性进行拍照
                this.windowSnapshot[prop] = window[prop];
            }
        }
        Object.keys(this.modifyPropsMap).forEach(p => {
            window[p] = this.modifyPropsMap[p];
        });
    }

    /**
    * 子应用卸载时,遍历当前子应用的window属性,和主应用的window快照做对比
    * 如果不一致,做两步操作 
    *     1. 保存 不一致的window属性,
    *     2. 还原window
    */
    inactive() {
        for (const prop in window) { // diff 差异
            if (window.hasOwnProperty(prop)) {
                // 将上次拍照的结果和本次window属性做对比
                if (window[prop] !== this.windowSnapshot[prop]) {
                    // 保存修改后的结果
                    this.modifyPropsMap[prop] = window[prop]; 
                    // 还原window
                    window[prop] = this.windowSnapshot[prop]; 
                }
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 优点

  • html entry的接入方式,不需要自己写load方法,而是直接写子应用的访问链接就可以。

  • 提供js沙箱

  • 提供样式隔离,两种方式可选 资源预加载,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度。

  • 社区活跃 umi 插件,提供了 @umijs/plugin-qiankun 供 umi 应用一键切换成微前端架构系统,除了最后一点拓展以外,微前端想要达到的效果都已经达到。

  • 应用间通信简单,全局注入路由保持,浏览器刷新、前进、后退,都可以作用到子应用

  • 路由保持,浏览器刷新、前进、后退,都可以作用到子应用

# 缺点

  • 改造成本较大,从 webpack、代码、路由等等都要做一系列的适配

  • 对 eval 的争议,eval函数的安全和性能是有一些争议的:MDN的eval介绍;

  • 无法同时激活多个子应用,也不支持子应用保活

  • 无法支持 vite 等 ESM 脚本运行,3.0 版本预计支持

# wujie

无界是腾讯推出的一款微前端解决方式。它是一种基于 Web Components + iframe 的全新微前端方案,继承iframe的优点,补足 iframe 的缺点,让 iframe 焕发新生。

# 实现方案

wujie跟qiankun一样,都是基于html entry加载的,但他们解析html的过程是不一样的。 qiankun是直接解析并执行js、css、html的,而wujie则是先解析html,提取出script脚本放入空的iframe中,提取出css、html放入到web components中,具体来说:

  1. 解析入口 HTML ,分别得到script、css、模版html
  2. 创建一个纯净的 iframe,为了实现应用间(iframe 间)通讯,无界子应用 iframe 的 url 会设置为主应用的域名(同域),因此 iframe 的 location.href 并不是子应用的 url。创建好后停止加载iframe
  3. iframe内插入js,将抽离出来的script脚本,插到iframe中去,在iframe中执行子应用的js
  4. 创建web component,id为子应用id,将抽离出来的html插入
  5. 由于iframe内的js有可能操作dom,但是iframe内没有dom,随意wujie框架内对iframe拦截document对象,统一将dom指向shadowRoot,此时比如新建元素、弹窗或者冒泡组件就可以正常约束在shadowRoot内部

# 优点

  • 接入简单,可以以组件的方式引入子应用

  • 纯净无污染

    • 无界利用iframe和webcomponent来搭建天然的js隔离沙箱和css隔离沙箱
    • 利用iframe的history和主应用的history在同一个top-level browsing context来搭建天然的路由同步机制
    • 副作用局限在沙箱内部,子应用切换无需任何清理工作,没有额外的切换成本
  • 支持vite esmoudle加载,由于js是独立在iframe中加载的,所以支持esmodule加载

  • 支持预加载

  • 支持应用保活,子应用状态保留,由于是独立在iframe中的,而切换应用时不会移除iframe,所以子应用的状态会被保留在原来的iframe中,当主应用再次渲染子应用dom时,会显示之前的状态。

  • 多应用同时激活在线

# 缺点

iframe沙箱的src设置了主应用的host,初始化iframe的时候需要等待iframe的location.orign从’about:blank’初始化为主应用的host,这个采用的计时器去等待的不是很优雅

# Micro App

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

采用iframe沙箱模式,这点和wujie的方案一样了,都是webComponent + iframe

# 实现方案

首先micro-app实现了一个基于WebComponent的组件,并实现了类Shadow Dom 的效果,开发者只需要用来加载子应用,整个对子应用的加载、js隔离、css隔离的逻辑都封装在了web component组件中,具体来说:

  1. 当调用microApp.start()后,会注册一个名为micro-app 的自定义 webComponent 标签。我们可以从 中拿到子应用的线上入口地址。
  2. 组件内部,当匹配到路由后,跟qiankun一样加载html,得到html字符串模版
  3. 分析html字符串,提取头和,并替换为框架自定义标签和
  4. 在<micro-app-head>内,会对script标签和link标签的内容进行加载并执行
  5. 将 <micro-app-head> 和 <micro-app-body> 插入到 <micro-app> 标签内
  6. <micro-app> 内提供了js沙箱方法(v1.0以前跟qiankun沙箱一样), <micro-app-head>挂载到 <micro-app> 后,内部会逐一对 <micro-app-head> 内的 script 标签的 js 绑定作用域,实现 js 隔离

# 优点

  • 接入简单,组件式引入子应用

  • 团队持续更新维护

  • js隔离、css隔离、路由同步

  • 支持子应用保活, 需要开启keep-alive模式 支持fiber模式,提升主应用的渲染性能。

# 缺点

  • 1.0之前不支持vite,1.0之后支持了

  • 默认css隔离方式,主应用的样式还是会污染到子应用。

  • 子应用和主应用必须相同的路由模式,要么同时hash模式,要么同时history模式

  • 依赖于CustomElements和Proxy两个较新的API。Proxy暂时没有做兼容,所以对于不支持Proxy的浏览器无法运行micro-app。

个人是比较看好 WebComponent 化的,侵入较低,接入更流畅。

它是由google推出的浏览器的原生组件,具体内容查看 链接 (opens new window) 了解

  • 复用性:不需要对外抛出加载和卸载的全局 API,可复用能力更强
  • 标准化:W3C 的标准,未来能力会得到持续升级
  • 插拔性:可以非常便捷的进行移植和组件替换

笔记

切记不要以为微前端而去微前端,老旧项目带来的迁移成本,不同项目技术栈的兼容与边界问题处理,因为没有迫切的需求而接入微前端,只会带来额外的负担,很多时候,iframe 其实就很够用了。

# 其他

# 联邦模块 (opens new window)

# 微前端实践 (opens new window)

编辑 (opens new window)
上次更新: 2025/2/14 17:17:30
前端实现权限控制

前端实现权限控制→

最近更新
01
IoC 解决了什么痛点问题?
03-10
02
如何调试 Nest 项目
03-10
03
Provider注入对象
03-10
更多文章>
Copyright © 2019-2025 Study | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式