文章目录
- 微前端的发展历史
- 微前端的定义
- 微前端的特点
- 使用微前端面临的挑战
- 微前端常用技术方案及优缺点
- 路由分发式微前端
- iframe
- single-spa
- qiankun
- webpack5: module federation
- Web Component
微前端的发展历史
微前端在2016年首次出现在TWTR(ThoughtWorks Technology Radar)上,把后端微服务的概念扩展到了前端世界。
微前端的定义
维基百科上对微服务的定义:**一种软件开发技术,面向服务的体系结构架构样式的一种变体,将应用程序构造为一组松散耦合的服务,并通过轻量级的通信协议组合起来。**具体来说,就是将一个单体应用按照一定的规则拆分为一组服务。这些服务,各自拥有自己的仓库,可以独立开发、独立部署,有独立的边界,可以由不同的团队进行管理,甚至可以使用不同的编程语言来编写。但对前端来说,仍然是一个完整的服务。
面对越来越重的前端应用,可将微服务的思想照搬到前端,就有了微前端的概念。像微服务一样,一个前端应用,也可以按照一定的规则,拆分为不同的子应用,独立开发,独立部署,然后聚合成一个完整的应用面对客户。
微前端的结构一般如下:
微前端的特点
- 简单、分离、松耦合的代码仓库。
对比应用“一大坨”的代码仓库,微前端架构下的代码仓库更加简单、轻量。各个仓库的代码可以基于业务、权限、变更的频率、组织结构、后端微服务等原则拆分,界限明确,降低耦合,便于开发人员在开发过程重快速定位源代码,降低维护成本。 - 独立开发、独立部署
代码库拆分后,我们可以基于各个代码仓库独立开发。由于代码体积的缩小,项目构建时间变短,极大提升开发效率。
各个项目都有自己的交付流水线(构建、测试、上线),并且能够独立部署,不需要考虑其他项目的情况。 - 技术栈无关
在实际的开发中,各个项目会因为各种各样的原因导致使用的技术栈不一样。比如,开发框架有react、vue、angluar等,构建工具有webpack、rollup、parcel 等,而且版本还可能不一样。使用微前端架构,可以将使用不同的技术栈(不同版本)的子应用聚合起来。 - 遗留系统迁移
在公司中,多多少少会有一些应用使用的是老的技术栈开发的,比如Backbone、Vue1.0、JQuery、Angluar2等。这些应用已经在线上稳定运行,而且也没有新的功能。对于这样的应用,我们没有理由去浪费时间和额外的经历,可以通过微前端方案直接整合到新的应用中。
当然,使用微前端很大一部分原因就是为了解决遗留系统的迁移问题。 - 技术栈升级
除了遗留系统迁移,微前端在技术栈版本升级方面也能提供帮助。
除了遗留系统迁移,微前端在技术栈升级方面也能提供帮助,ant-design已经更新到了5,但是项目因为一直在迭代,还是使用antd2。如果直接重构,肯定是不现实的,不仅费事费力,而且风险也比较大。
对于这种情况,我们可以重起一个应用,使用antd4 循序渐进的重构应用,然后使用微前端方案将新旧应用聚合起来。 - 团队技术成长
和微前端技术栈无关的优点,可以让团队获得更多的机会在项目中尝试新的技术(Vue3、Webpack5 等),有助于整个团队的成长。
使用微前端面临的挑战
微前端方案给我们带来巨大便利的同时,也给我们带来了一些挑战。在实现微前端的同时,我们必须要考虑的问题:
- 子应用切换
- 应用相互隔离,互不干扰
- 子应用之间通信
- 多个子应用并存
- 用户状态的存储 - 免登
微前端常用技术方案及优缺点
目前主流的微前端实现方案主要有:
- 路由分发式微前端
- iframe
- single-spa
- qiankun
- webpack5:module federation
- Web Component
路由分发式微前端
路由分发式微前端,就是通过路由将不同的业务分发到不同的独立前端应用上。最常用的方案是通过 http服务的反向代理来实现。
🌰栗子<( ̄▽ ̄)/(一个基于路由分发的Nginx配置):
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作为一项非常古老的技术,也可以用于实现微前端、通过iframe,我们可以很方便的将一个应用嵌入到另一个应用中,而且两个应用之间的 css 和 js 是相互隔离的,不会互相干扰。
优点:
- 用户体验不好,每次切换应用时,浏览器需要重新加载页面。
- UI不同步,DOM结构不共享;
- 全局上下文完全隔离,内存变量不共享,子应用之间通信、数据同步过程较复杂。
- 对SEO不友好
- 子应用切换时可能需要重新登录,体验不好。
single-spa
路由转发模式、iframe模式尽管可以实现微前端,但是体验不好。每次切换已经访问过的子应用时,都需要重新加载子应用,对性能有很大影响。
现在前端应用开发的主流模式为基于vue、react、angluar 的单页面应用开发模式。在这种模式下,我们需要维护一个路由注册表,每个路由对应各自的页面组件url。切换路由时,如果是一个新的页面,需要动态获取路由对应的js脚本,然后执行脚本并渲染出对应的页面;如果是一个已经访问过的页面,那么直接从缓存中获取已缓存的页面方法,执行并渲染出对应的页面。
微前端也有类似的实现方案,来获得和单页应用一样的用户体验。
在single-spa方案中,应用被分为两类:基座应用和子应用。其中,子应用就是需要聚合的子应用;而基座应用,是另外一个单独的应用,用于聚合子应用。
和单页应用的实现原理类似,single-spa 会在基座应用中维护一个路由注册表,每个路由对应一个子应用。基座应用启动后,当我们切换路由时,如果是一个新的子应用,会动态获取子应用的js脚本,然后执行脚本并渲染出相应的页面;如果是一个访问过的子应用,那么就会从缓存中获取已经缓存的子应用,激活子应用并渲染出对应的页面。
优点:
- 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验
- 完全技术栈无关
- 多个子应用可并存
- 生态丰富
缺点: - 需要对原有应用进行改造,应用要兼容接入single-spa 和独立使用
- 有额外的学习成本
- 使用复杂,关于子应用加载、应用隔离、子应用通信等问题,需要框架使用者自己实现。
- 子应用间相同资源重复加载
- 启动应用时,要先启动基座应用
qiankun
和 single-spa 一样,qiankun 也能提供类似单页应用的用户体验。qiankun 是在 single-spa的基础上,做了二次开发,在框架层面解决了使用single-spa 时需要开发人员自己编写子应用加载、通信、隔离等逻辑的问题,是一种比 single-spa 更优秀的微前端方案。
优点:
- 切换应用时,浏览器不用重载页面,提供和单页面一样的用户体验
- 相比single-spa,解决了子应用加载、应用隔离、子应用通信等问题,使用起来相对简单。
- 完全和技术栈无关
- 多个子应用可并存
缺点: - 需要对原有应用进行改造,应用要兼容接入qiankun和独立使用;
- 有额外的学习成本
- 相同资源重复加载
- 启动应用时,要先启动基座应用
webpack5: module federation
webpack5 提供一个新特性 module fedaration 。基于这个特性,我们可以在一个 js 应用中动态加载并运行另一个js 应用的代码,并实现应用之间的依赖共享。
通过module federation,我们可以在一个应用里动态渲染另一个应用的页面,这样也就实现了多个子应用的聚合。
module federation,我们可以在一个应用里动态渲染另一个应用的页面,这样也就实现了多个子应用的聚合。
优点:
- 不需要对原有应用进行改造,只需改造打包脚本
- 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验。
- 多个子应用可并存
- 相同资源不需要重复加载
- 开发技术栈无关
- 应用启动后,无需加载与自己无关的资源
- 免登友好
缺点: - 构建工具只能使用 webpack5
- 有额外的学习成本
- 对有项目不友好,需要对webpack 进行改造
Web Component
基于Web Component 的 Shadow Dom 能力,我们也可以实现微前端,将多个子应用聚合起来。
Shadow Dom 的应用如下:
const shadow = document.querySelector('#hostElement').attachShadow({mode: "open"});
// fetch 为应用的地址,基于fetch,可以获取应用html模版,添加到指定节点下
fetch(url).then(res => {shadow.innerHTML = res;
});
优点:
- 实现简单
- css和js天然隔离,互不干扰
- 完全技术栈无关
- 多个子应用可以并存
- 不需要对现有应用进行改造
缺点: - 主要是浏览器兼容性问题
- 开发成本较高