个人平时比较喜欢捣鼓一些前端的技术,在和群友聊天的时候,了解到了微前端这个概念
然后在实习的时候公司也用到了微前端的相关概念,使用iframe将多个子应用嵌套在一起
在维护项目的时候,感觉不管是启动还是加应用的速度都是比较慢的
在后面有时间的时候我就捣鼓捣鼓了当前比较流行的微前端框架:qiankun
今天来纪录一些关于微前端的一些知识
如果你想了解我关于微前端的简单应用,直达链接:qiankun的使用 - 鲸落 (xiaojunnan.cn)
当前,基于 vue、react、angular 的单页应用开发模式已经成为业界主流。受益于它们丰富的生态,我们可以使用这些技术快速构建一个新的应用,迅速响应市场。随着公司业务的不断发展,应用开始变得庞大臃肿,逐渐成为一个巨石应用,难以维护不说,每次开发、上线新需求时还需要花费不少的时间来构建项目,对开发人员的开发效率和体验都造成了不好的影响。因此将一个巨石应用拆分为多个子应用势在必行。
一般情况下,我们会基于业务来拆分应用。每个应用都有一个自己的仓库,独立开发、独立部署、独立访问、独立维护,还可以根据团队的特点自主选择适合自己的技术栈,极大的提升了开发人员的效率和体验。
应用拆分能给我们带来便利,但同时也给我们带来了新的挑战,那就是应用的聚合。对于客户来说,他们在使用我们的产品时,更希望呈现在自己面前的是一个完整的应用,而不是分散的多个子应用。因此我们需要选择一个合适的方案,能兼容不同的技术栈,将已经拆分的子应用重新聚合。
而微前端,正是这样一个合适的方案,来帮助我们面对上述挑战。
微前端,早已是一个老生常谈的概念,它于 2016 年首次出现在 ThoughtWorks Technology Radar 上,将后端微服务的概念扩展到了前端世界。
微服务,维基上对其定义为:一种软件开发技术- 面向服务的体系结构(SOA)架构样式的一种变体,将应用程序构造为一组松散耦合的服务,并通过轻量级的通信协议组织起来。具体来讲,就是将一个单体应用,按照一定的规则拆分为一组服务。这些服务,各自拥有自己的仓库,可以独立开发、独立部署,有独立的边界,可以由不同的团队来管理,甚至可以使用不同的编程语言来编写。但对前端来说,仍然是一个完整的服务。
微服务,主要是用来解决庞大的一整块后端服务带来的变更和扩展的限制。
同样的,面对越来越重的前端应用,可将微服务的思想照搬到前端,就有了微前端的概念。像微服务一样,一个前端应用,也可以按照一定的规则,拆分为不同的子应用,独立开发,独立部署,然后聚合成一个完整的应用面对客户。
- 独立开发、独立部署
- 技术栈无关
- 简单、分离、松耦合的代码仓库
- 遗留系统迁移
- 对于一些使用老技术栈开发的应用,我们没有理由浪费时间和精力,可以通过微前端方案直接整合到新的应用中。
- 技术栈升级
- 我们可以重起一个应用,循序渐进的重构应用,然后使用微前端方案将新旧应用聚合在一起。
微前端方案给我们带来巨大便利的同时,也给我们带来了新的挑战。在实现微前端应用时,我们必须要考虑以下问题:
- 子应用切换
- 应用相互隔离,互不干扰
- 子应用之间通信
- 多个子应用并存
- 用户状态的存储 - 免登
目前,业界主流的微前端实现方案主要有:
- 路由分发式微前端
- iframe
- single-spa
- qiankun
- webpack5:module federation
- Web Component
路由分发式微前端,即通过路由将不同的业务分发到不同的独立前端应用上。最常用的方案是通过 HTTP 服务的反向代理来实现。
在部署服务器的时候设置代理,请求不通的路径
http {
server {
listen 80;
server_name xxx.xxx.com;
location /api/ {
proxy_pass http://localhost:3001/api;
}
location /web/admin {
proxy_pass http://localhost:3002/api;
}
location / {
proxy_pass /;
}
}
}
优点:
缺点:
- 用户体验不好,每次切换应用时,浏览器都需要重新加载页面
- 多个子应用无法并存
- 局限性比较大
- 子应用之间的通信比较困难
- 子应用切换时需要重新登录
iframe 作为一项非常古老的技术,也可以用于实现微前端。通过 iframe,我们可以很方便的将一个应用嵌入到另一个应用中,而且两个应用之间的 css 和 javascript 是相互隔离的,不会互相干扰。
优点:
- 实现简单
- css 和 js 天然隔离,互不干扰
- 完全技术栈无关
- 多个子应用可以并存
- 不需要对现有应用进行改造
缺点:
- 用户体验不好,每次切换应用时,浏览器需要重新加载页面
- UI 不同步,DOM 结构不共享
- 全局上下文完全隔离,内存变量不共享,子应用之间通信、数据同步过程比较复杂
- 对 SEO 不友好
- 子应用切换时可能需要重新登录,体验不好
官网:single-spa
路由转发模式、iframe 模式尽管可以实现微前端,但是体验不好。我们每次切换回已经访问过的子应用时,都需要重新加载子应用,对性能有很大的影响。
我们知道,现在前端应用开发的主流模式为基于 vue / react/ angular 的单页应用开发模式。在这种模式下,我们需要维护一个路由注册表,每个路由对应各自的页面组件 url。切换路由时,如果是一个新的页面,需要动态获取路由对应的 js 脚本,然后执行脚本并渲染出对应的页面;如果是一个已经访问过的页面,那么直接从缓存中获取已缓存的页面方法,执行并渲染出对应的页面。
那么,微前端也有没有类似的实现方案,来获得和单页应用一样的用户体验呢?
答案是有的。 single-spa 提供了新的技术方案,可以帮忙我们实现类似单页应用的体验。
在 single-spa 方案中,应用被分为两类:基座应用和子应用。其中,子应用就是文章上面描述的需要聚合的子应用;而基座应用,是另外的一个单独的应用,用于聚合子应用。
和单页应用的实现原理类似,single-spa 会在基座应用中维护一个路由注册表,每个路由对应一个子应用。基座应用启动以后,当我们切换路由时,如果是一个新的子应用,会动态获取子应用的 js 脚本,然后执行脚本并渲染出相应的页面;如果是一个已经访问过的子应用,那么就会从缓存中获取已经缓存的子应用,激活子应用并渲染出对应的页面。
优点:
- 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验
- 完全技术栈无关
- 多个子应用可并存
- 生态丰富
缺点:
- 需要对原有应用进行改造,应用要兼容接入 sing-spa 和独立使用
- 有额外的学习成本
- 使用复杂,关于子应用加载、应用隔离、子应用通信等问题,需要框架使用者自己实现
- 子应用间相同资源重复加载
- 启动应用时,要先启动基座应用
官网:qiankun
和 single-spa 一样,qiankun 也能给我们提供类似单页应用的用户体验。qiankun 是在 single-spa 的基础上做了二次开发,在框架层面解决了使用 single-spa 时需要开发人员自己编写子应用加载、通信、隔离等逻辑的问题
优点:
- 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验
- 相比 single-spa,解决了子应用加载、应用隔离、子应用通信等问题,使用起来相对简单
- 完全和技术栈无关
- 多个子应用可并存
缺点:
- 需要对原有应用进行改造,应用要兼容接入 qiankun 和独立使用
- 有额外的学习成本
- 相同资源重复加载
- 启动应用时,要先启动基座应用
webpack5,提供了一个新的特性 - module federation。基于这个特性,我们可以在一个 javascript 应用中动态加载并运行另一个 javascript 应用的代码,并实现应用之间的依赖共享。
通过 module federation,我们可以在一个应用里面动态渲染另一个应用的页面,这样也就实现了多个子应用的聚合。
优点:
- 不需要对原有应用进行改造,只需改造打包脚本
- 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验
- 多个子应用可并存
- 相同资源不需要重复加载
- 开发技术栈无关
- 应用启动后,无需加载与自己无关的资源
- 免登友好
缺点:
- 构建工具只能使用 webpack5
- 有额外的学习成本
- 对老项目不友好,需要对 webpack 进行改造
案例:京东的开源微前端框架 MicroApp (micro-zoe.github.io)
基于 Web Component 的 Shadow Dom 能力,我们也可以实现微前端,将多个子应用聚合起来。
优点:
- 实现简单
- css 和 js 天然隔离,互不干扰
- 完全技术栈无关
- 多个子应用可以并存
- 不需要对现有应用进行改造
缺点:
还有许多优秀的微前端框架,如字节跳动的Garfish, 阿里飞冰团队的icestark 等等。有需要了解的可以深入了解一下
参考链接
微前端学习系列(一):微前端介绍 - 掘金 (juejin.cn)