前端微服务化方案对比:路由懒加载 vs 子应用模式
撸了个新框架 Mooa,用于前端应用的微服务化拆分。
过去的几周里,作为一个 “专业” 的咨询师,一直忙于在为客户设计一个应用拆分的服务化方案。主要是为了达成以下的设计目标:
构建插件化的 Web 开发平台,满足业务快速变化及分布式多团队并行开发的需求
构建服务化的中间件,搭建高可用及高复用的前端微服务平台
支持前端的独立交付及部署
简单地来说,就是要支持应用插件化开发,以及多团队并行开发。
应用插件化开发
应用插件化开发,其所要解决的主要问题是:臃肿的大型应用的拆分问题。大型前端应用,在开发的时候要面临大量的遗留代码、不同业务的代码耦合在一起,在线上的时候还要面临加载速度慢,运行效率低的问题。
前端微服务化:路由懒加载
路由懒加载,即通过不同的路由来将应用切成不同的代码快,当路由被访问的时候,才加载对应组件。
在诸如 Angular、Vue 框架里都可以通过路由 + Webpack 打包的方式来实现。不可避免地就会需要一些问题:
难以多团队并行开发,路由拆分就意味着我们仍然是在一个源码库里工作的。也可以尝试拆分成不同的项目,再编译到一起,可能会导致以下问题:
运行效率变慢,在这种情况下使用懒加载时,无法使用 AoT(Ahead-of-time,提前编译),只能使用 JIT(Just In Time即时编译)。使用 AOT,浏览器下载预编译版本的应用程序,而不是等应用完成首次编译——不过,编译 HTML 和 CSS 编译后的 JavaScript 体积更大。它也就意味着,我们需要引入整个 Angular 编译器,该编译器差不多占了 Angular 自身体积的一半儿。
首屏加载可能没有变快,当我们使用 Webpack 来分开打包的时候,目前的 Webpack 没有办法区分中那些方法是用不到的函数,与此同时还不能对 js 进行 uglify,因为子模块可能找不到对应的依赖。这就意味着,有大量的不需要用到的 JS 代码,被加入到了 Vendor 文件中;与此同时,它们还是没有压缩(uglify)的代码。
每次发布需要重新编译,是的,当我们只是更新一个子模块的代码,我们要重新编译整个应用,再重新发布这个应用。而不能独立地去构建它,再发布它。
统一的 Vendor 版本,统一第三方依赖是一件好事。可问题的关键在于:每当我们添加一个新的依赖,我们可能就需要开会讨论一下。
然而,最大的问题就是难以多团队并行开发,这里之所以说的是 “难以” 是因为,还是有办法解决这个问题。在日常的开发中,一个小的团队会一直在一个代码库里开发,而一个大的团队则应该是在不同的代码库里开发。
对于一个二三十人规模的团队来说,他们可能在业务上归属于不同的部门,技术上也有一些不一致的规范,如 4 个空格、2 个空格还是使用 Tab 的问题。特别是当它是不同的公司和团队时,他们可能要放弃测试、代码静态检测、代码风格统一等等的一系列问题。
微服务化方案:子应用模式
除了路由懒加载,我们还可以采用子应用模式,即每个应用都是相互独立地。即我们有一个基座工程,当用户点击相应的路由时,我们去加载这个独立 的 Angular 应用;如果是同一个应用下的路由,就不需要重复加载了。而且,这些都可以依赖于浏览器缓存来做。
除了路由懒加载,还可以采用的是类似于 Mooa 的应用嵌入方案。如下是基于 Mooa 框架 + Angular 开发而生成的 HTML 示例:
<app-root _nghost-c0="" ng-version="4.2.0"> ... <app-home _nghost-c2=""> <app-app1 _nghost-c0="" ng-version="5.2.8" style="display: none;"><nav _ngcontent-c0="" class="navbar"></app-app1> <iframe frameborder="" width="100%" height="100%" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="http://localhost:4200/app/help/homeassets/iframe.html" id="help_206547"></iframe> </app-home></app-root>
Mooa 提供了两种模式,一种是基于 Single-SPA 的实验做的,在同一页面加载、渲染两个 Angular 应用;一种是基于 iFrame 来提供独立的应用容器。
解决了以下的问题:
首页加载速度更快,因为只需要加载首页所需要的功能,而不是所有的依赖。
多个团队并行开发,每个团队里可以独立地在自己的项目里开发。
独立地进行模块化更新,现在我们只需要去单独更新我们的应用,而不需要更新整个完整的应用。
但是,它仍然包含有以下的问题:
重复加载依赖项,即我们在 A 应用中使用到的模块,在 B 应用中也会重新使用到。有一部分可以通过浏览器的缓存来自动解决。
第一次打开对应的应用需要时间,当然预加载可以解决一部分问题。
在非 iframe 模式下运行,会遇到难以预料的第三方依赖冲突。
共同学习,写下你的评论
评论加载中...
作者其他优质文章