微前端解决的问题
- 跨框架: 在一个页面上运行,可以同时使用多个框架
- 应用拆分:将一个复杂的应用拆解为多个微小的应用,类似后端的微服务。
- 遗留系统迁移:让旧的前端框架可以直接嵌入到现有的应用进行。
微前端的技术拆分方式
路由分发式
通过HTTP服务的反向代理功能或者是应用框架自带了的路由,将请求分发到不同的独立前端应用上。这种方式适合用来做遗留系统迁移。
问题:
- 当用户从一个应用到另外一个应用时,需要刷新页面、重新加载资源文件。
- 缺少应用状态处理。
特点:
- 需要关注应用间的数据传递方式。从应用A传递数据到应用B,如果是这些应用是在一个域里面,则可以通过LocalStorage、Cookies、IndexedDB等共享数据。
- 一个页面只有一个应用。
使用NGINX路由分发的例子,如下:
server {
listen 80;
server_name www.demo.com;
location /api/ {
proxy_pass http://127.0.0.1:8080/api;
}
location /client {
proxy_pass http://127.0.0.1:8080/client;
}
location /admin {
proxy_pass http://127.0.0.1:8080/admin;
}
}
前端微服务化
这种方式下,每个前端应用都是相互独立的(开发、部署、构建、运行),然后通过模块化的方式组合完整的前端应用。
特点:
- 一个页面上可以运行多个前端应用。
- 需要在页面合适的地方引入或创建DOM。
- 用户操作时,要加载对应的应用,也能卸载应用(移除DOM和对应应用的监听)。
- 应用间的第三方依赖不能冲突,也就是说应用A和B不能引入某个插件的不同版本,如果出现了这样的冲突,就需要去解决。
实践方式:
如上图所示,这是个基座模式,就是通过一个主应用,来管理其它应用。每个项目对基座的要承担功能定义不一样,我看的书里的项目对基座包含的功能有:(1)管理其他子应用(2)负责应用之间的通信(3)设计路由的响应机制(4)支持嵌入常规和iframe模式。可以用来参考。
以上的图是书里的基座设计的一个流程。
(1)应用注册表的服务【最右边】:它是一个固定值的配置文件,或是一个可动态更新的配置,或是一种动态的服务。应用注册表的服务主要是为了有以下的一些内容:
- 应用发现。让主应用可以寻找到其它应用。
- 应用注册。向应用注册表注册新的微前端应用功能。
- 第三方应用注册。让第三方应用,可以接入到系统中。
- 访问权限等相关配置。
(2)主工程从服务器获取最新的应用配置
(3)主工程获取配置后,创建应用并初始化。
(4)主工程监测到路由变化,确认是否有路由对应的应用,找到匹配的应用后,加载对应的应用。
可用的框架:
Single-SPA: 有大部分框架( React、Angular、Vue 等)的启动和卸载处理。
Mooa:基于 Single-SPA 为 Angular 框架设计的一个微前端架构应用。
微应用
开发的都是单一的微小应用,然后通过工程的方式,在部署构建时把多个独立的应用组合成一个新的单体应用。
一个大的前端项目,往往从文件目录上就已经进行了模块的拆分。这种方式下,就是把各个模块加上共享部分的代码成为一个单独的应用。在构建整个前端项目时,复制所有的模块到一个项目中,进行集成构建。
问题:
- 只能使用统一的前端框架。
- 所有应用的依赖版本要统一。
- 非常依赖于持续集成,只要有一个子应用更新了,就需要重新构建整个应用。
实践例子:
1.有一个主代码库,这个代码库里是一个空白的angular框架代码,可以独立构建包含另外几个应用的完整代码。
2.manager应用,这个应用内是一个完整的angular应用,是可以独立开发运行的。
3.各个应用,同2.
4.构建过程:(1)从远程拉取最新代码;(2)更新子应用代码到主应用中的占位模块:把manager等子应用对应的模块和代码copy到主工程中,其实就是拷贝manager路径下的代码到主工程中。(3)可能还会有一些文本替换的内容。
5.持续集成:子应用代码有更新就要出发对应模块的构建,构建完成再触发整个系统的构建;主应用代码更新触发整个系统的构建。如果为了避免频繁的构建,可以考虑定时构建的方式。
微件化
微件(Widget)指的是可以直接嵌入应用,能运行的代码,需要预编译好。
Widget的形式有:
- 分包构建出来的独立代码,例如webpack构建出来的chunk文件。
- 使用DSL方式编写出来的组件。
特点:
- 必须要有一个基础的完整的框架来运行和编译环境,确保Widget是可用的。【239页(第一行运行时及编译环境)】
- 需要规划好依赖,当一个Widget想要使用新的依赖,需要在上游中引入这个依赖。
- 需要一个能用于构建独立Widget模块的构建系统,所以需要改写webpack,使得它能支持构建出单个代码段。
问题:
- 因为是运行时才编译的,所以对比于预先编译的应用,性能方面会受影响。
- 实施成本比微应用化高。
实践:
如上图,在实践中,编写不同的业务代码,将部分业务功能构建成独立的chunk代码,把编译好的代码放到指定的服务器上【微件中心】。运行时,只需要加载对应的业务模块代码就可以了。更新的时候同样只需要更新对应模块的代码。
前端容器化(iframe)
将iframe作为容器来容纳其他前端应用。iframe可以把另一个网页或者单页面应用嵌入当前页面中,并且iframe中的网页和其他网页相互独立。使用iframe需要设计好加载机制和通信机制,也就是说要定义好什么时候加载、卸载应用;通信的事件名规范是什么、什么时候去监听/解绑事件监听。
特点:
- 网站不需要SEO支持。
- 兼容性良好。
应用组件化
借助于Web Components技术,来构建跨框架的前端应用。
Web Components可以允许我们创建可重用的定制元素,并且在web应用中使用它们。Angular框架中已经支持把当前应用构建成一个Web Components组件了。React也能够支持引入Web Components组件。实践中,还需要构建出Web Components组件,然后在页面中引入这些Web Components组件,使用方式有点像微件化。
Web Components是由Custom Elements、Shadow Dom、HTML Templates、HTML Imports组成的。
问题:
-
Web Components浏览器的兼容性还没有很高。
选择哪一种微前端方案
可以参考《前端架构:从入门到微前端》的作者博客:微前端架构选型指南
学习书籍:
《前端架构:从入门到微前端》