背景
-
美业PC作为一个单体应用经历4年迭代开发,代码量和依赖庞大,纯业务代码经统计有60多万行
-
工程方面,构建部署的速度极慢,开发人员本地调试体验差效率低,一次简单的构建+发布需要7+8=15分钟以上
-
代码方面,业务代码耦合严重,影响范围难以收敛,多次带来了“蝴蝶效应”式的的线上Bug和故障
-
技术方面,通用依赖升级带来的改动和回归成本巨大,涉及例如Zent组件、中台组件等依赖包相关的日常需求和技术升级几乎不可推动
-
测试方面,单应用应对多人和多项目发布,单应用发布总和高且非常频繁,每次的集成测试都有冲突处理和新问题暴露的风险
-
组织方面,单应用也无法很好应对业务小组的开发组织形式,边界职责不清晰且模块开发易干扰
-
架构方面,前端无法和后端形成对应的领域应用开发模式,不利于业务的下沉,也无法支持前端能力的服务化和对技术栈的演进依赖
总体来说,臃肿的单体应用模式,给开发人员带来了无法忍受的难处,给快速支撑业务带来了很大的瓶颈,也没有信心应对接下来的业务的继续拓展。对美业PC进行架构调整就是非常迫切和有价值的事情了
目标
-
业务架构层面,围绕美业PC的业务形态、项目架构以及发展趋势,将大型多团队协同开发的前端应用视为多个独立团队所产出功能的组合。
-
技术架构层面,解耦大型前端应用,拆分成基座应用、微前端内核、注册中心、若干独立开发部署的子系统,形成分布式体系的中心化治理系统。
-
软件工程方面,保证渐进式迁移和改造,保证新老应用的正常运行。
达成价值
业务价值
-
实现了前端为维度的产品的原子化,如果整合新业务,子应用可以快速被其他业务集成
-
以业务领域划分,让组织架构调整下的项目多人协作更职责清晰和成本低,且适应组织架构调整
-
减慢系统的熵增,铺平业务发展道路。
工程价值
-
实现了业务子应用独立开发和部署,构建部署的等待耗时从15分钟降到了1分半
-
支持渐进式架构,系统子应用之间依赖无关,可以单个升级依赖,技术栈允许不一致,技术迭代的空间更大
-
前端能力能够服务化输出
-
架构灵活,新的业务可以在不增加现存业务开发人员认知负担的前提下,自由生长无限拓展
缺点
一个架构的设计其实对整体的一个权衡和取舍,除了价值和优势之外,也带来一些需要去考虑的影响。
缺点
Part 02 架构与工程
从全局视角把握成果
微前端方案有哪些
-
使用 HTTP 服务器反向代理到多个应用
-
在不同的框架之上设计通讯、加载机制
-
通过组合多个独立应用、组件来构建一个单体应用
-
使用 iFrame 及自定义消息传递机制
-
使用纯 Web Components 构建应用
-
结合 Web Components 构建
微前端
每种方案都有自己的优劣,我们兄弟团队采用了最原始的网关转发配置类似 Nginx 配置反向代理,从接入层的角度来将系统组合,但是每一次新增和调整都需要在运维层面去配置。
而 iframe 嵌套是最简单和最快速的方案,但是 iframe的弊端也是无法避免的。
Web Components的方案则需要大量的改造成本。
组合式应用路由分发方案改造成本中等且满足大部分需求,也不影响个前端子应用的体验,是当时比较先进的一种方案。
架构设计选型注意点
-
如何降低系统的复杂度?
-
如何保障系统的可维护性?
-
如何保障系统的可拓展性?
-
如何保障系统的可用性?
-
如何保障系统的性能?
综合评估之后我们选用了组合式应用路由分发方案,但是仍然有架构整体蓝图和工程实现需要去设计。
需求分析
-
子应用独立运行/部署
-
中心控制加载(服务发现/服务注册)
-
子应用公用部分复用
-
规范子应用的接入
-
基座应用路由和容器管理
-
建立配套基础设施
设计原则
-
支持渐进式迁移,平滑过渡
-
拆分原则统一,尝试领域划分来解耦
应用架构图
应用架构图
系统拆分
系统拆分
这里拆分需要说明三个点:
-
独立部署(服务注册):上传应用资源包(打包生成文件)到Apollo配置平台,是一个点睛之笔
-
服务化和npm包插件化的区别是不需要通过父应用构建来集成,彼此依赖无关,发布独立,更加灵活/可靠
-
同时 Apollo 承载了注册中心的功能,可以省去子应用的web服务器的这一层,简化了架构
时序图
时序图
前端流程图
流程图
## Part 03 关键技术
落地中有哪些值得一提的技术细节
关键技术一览
我们按项目拆分来结构化讲述,有架构核心、注册中心、子应用、代码复用四篇。
其中包含了这些技术点:
-
Apollo
-
Apollo Cli
-
Version Manage
-
Sandbox
-
RouterMonitor
-
MicroPageLoader
-
Shared Menu
-
Shared Common
[架构核心]消息通信
消息通信
消息通信1
消息通信2
消息通信3
[架构核心]路由分发
路由分发
当浏览器的路径变化后,最先接受到这个变化的是基座的router,全部的路由变化由基座路由 RouterMonitor 掌管,因为它会去劫持所有引起url变化的操作,从而获取路由切换的时机。如果是apps/xxx/#
之前的变化,只会拦截阻止浏览器再次发起网页请求不会下发,没有涉及#之前的url变化就下发到子应用,让子应用路由接管。
[架构核心]应用隔离
主要分为 JavaScript执行环境隔离 和 CSS样式隔离。
JavaScript 执行环境隔离:每当子应用的JavaScript被加载并运行时,它的核心实际上是对全局对象 window 的修改以及一些全局事件的的改变,例如 JQuery 这个js运行之后,会在 window 上挂载一个 window.$ 对象,对于其他库 React、Vue 也不例外。为此,需要在加载和卸载每个子应用的同时,尽可能消除这种冲突和影响,最普遍的做法是采用沙箱机制 SandBox。
沙箱机制的核心是让局部的 JavaScript 运行时,对外部对象的访问和修改处在可控的范围内,即无论内部怎么运行,都不会影响外部的对象。通常在 Node.js 端可以采用 vm 模块,而对于浏览器,则需要结合 with 关键字和 window.Proxy 对象来实现浏览器端的沙箱。
CSS 样式隔离:当基座应用、子应用同屏渲染时,就可能会有一些样式相互污染,如果要彻底隔离 CSS 污染,可以采用 CSS Module 或者命名空间的方式,给每个子应用模块以特定前缀,即可保证不会相互干扰,可以采用 webpack 的 postcss 插件,在打包时添加特定的前缀。
对于子应用与子应用之间的CSS隔离就非常简单,在每次应用加载是,就将改应用所有的 link 和 style 内容进行标记。在应用卸载后,同步卸载页面上对应的 link 和 style 即可。
[架构核心]核心流程图
我们把路由分发、应用隔离、应用加载、通用业务逻辑收纳到到了微前端内核的二方包中,用作各个业务线复用,在内部达成统一约定。
内核流程图
[注册中心]Apollo
其实大部分公司在落地微前端方案的时候,并有没所谓的注册中心的概念。为什么我们的微前端也会有注册中心这个概念和实际存在呢?选型的思考点也主要来自我们后端的微服务架构。
注册中心
为什么选择引入注册中心增加整体架构的复杂度?
两个原因:
-
我们的子应用之间虽然不需要通信,但是也存在基座应用需要所有子应用的资源信息的情况,用来维护路由对应子应用资源地址的映射。大部分公司落地时候,都把子应用的地址信息硬编码到了基座。这样子应用增删改时候,就需要去重新部署基座应用,这违背了我们解耦的初衷。注册中心把这份映射文件从基座剥离出来了,让架构具备了更好的解耦和柔性。
-
要知道我们的子应用的产物入口是 hash 化的上传到 CDN 的 JS 文件,同时避免子应用发布也需要发布基座应用。有两个解决方案,一种是增加子应用的 Web 服务器,可以通过固定的 HTTP 服务地址拿到最新的静态资源文件。一种就是增加注册中心,子应用发布就是推送新的 JS地址给到 注册中心,子应用的架构就可以更薄。
需要一个注册中心的话,我们也有两种方案,一种是自己自研一个专门服务于自己的微前端,虽然可以更加贴合和聚焦,但是作为注册中心,高可用的技术底层要求下的熔断降级等机制必不可少,这些研发难度大成本也高。还有一种是直接应用成熟的提供注册中心能力的开源项目或者依赖公司的已经存在的技术设施组件。
最后我们确定在选用公司内部的基础技术设施的 Apollo 项目,优势有这么两方面。
-
项目本身开源,成熟程度很高,在多环境、即时性、版本管理、灰度发布、权限管理、开放API、支持端、简单部署等功能性方面做得很不错,是一个值得信赖的高可用的配置中心。
-
公司内部针对做了私有化定制和部署,更加适配业务,并且在 Java 和 Node 场景下都有稳定和使用,有维护人员值班。
apollo-basic
子应用的打包构建体验
-
定位:一个子应用构建完是一个带 hash 的静态资源,等待被基座加载。
-
怎么做:
-
打包一个单入口的静态资源,同时暴露全局方法给基座
-
每次构建生成带 hash 的入口 app.js
-
获取打包产出生成上传配置
-
根据环境参数上传到apollo
-
体验如何
非常轻量,无须发布,构建即可
子应用如何推送打包完成的 cdn 地址给 Apollo
apollo页面
-
获取打包完成的产物的 JSON,获取入口文件 Hash,和当前项目的基础信息。
-
基于上述配置生成内容,然后调用 Apollo 平台开放的 API 上传到 Apollo。
如何进行多环境发布及服务链协作
微应用发布
- 环境主要分为测试、预发、生产。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
最后更多分享:前端字节跳动真题解析
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
存中…(img-P1B7qoY1-1712779452710)]
[外链图片转存中…(img-OfCJvSdn-1712779452710)]
[外链图片转存中…(img-o5LJhFPP-1712779452710)]
[外链图片转存中…(img-YFO3dWwi-1712779452711)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-rxsOzy2n-1712779452711)]
最后更多分享:前端字节跳动真题解析
- [外链图片转存中…(img-aozLKOjl-1712779452711)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-wo56xa2u-1712779452711)]