《微前端架构简介.docx》由会员分享,可在线阅读,更多相关《微前端架构简介.docx(9页珍藏版)》请在第一文库网上搜索。
1、微前端架构开发简介一 .简介为了解决庞大的一整块后端服务带来的变更与扩展方面的限制,出现了微服务架构(Microservices):微服务是面向服务架构(SOA)的一种变体,把应用程序设计成一系列松耦合的细粒度服务,并通过轻量级的通信协议组织起来具体地,将应用构建成一组小型服务。这些服务都能够独立部署、独立扩展,每个服务都具有稳固的模块边界,甚至允许使用不同的编程语言来编写不同服务,也可以由不同的团队来管理然而,越来越重的前端工程也面临同样的问题,自然地想到了将微服务思想应用(照搬)到前端,于是有了一微前端(micro-frontends)的概念:Micro frontends, An arc
2、hitectural style where independently deliverable frontend applicationsare composed into a greater whole.即,一种由独立交付的多个前端应用组成整体的架构风格。具体的,将前端应用分解成一些更小、更简单的能够独立开发、测试、部署的小块,而在用户看来仍然是内聚的单个产品:Decomposing frontend monoliths into smaller, simpler chunks that can be developed, tested anddeployed independently,
3、 while still appearing to customers as a single cohesive product.二 .特点简单来讲,微前端的理念类似于微服务:In short, micro frontends are all about slicing up big and scary things into smaller, moremanageable pieces, and then being explicit about the dependencies between them.将庞大的整体拆成可控的小块,并明确它们之间的依赖关系。关键优势在于:代码库更小,更内聚
4、、可维护性更高松耦合、自治的团队可扩展性更好渐进地升级、更新甚至重写部分前端功能成为了可能1 .简单、松耦合的代码库比起一整块的前端代码库,微前端架构下的代码库倾向于更小/简单、更容易开发此外,更重要的是避免模块间不合理的隐式耦合造成的复杂度上升。通过界定清晰的应用边界来降低意外耦合的可能性,增加子应用间逻辑耦合的成本,促使开发者明确数据和事件在应用程序中的流向2 .增量升级理想的代码自然是模块清晰、依赖明确、易于扩展、便于维护的然而,实践中出于各式各样的原因:历史项目,祖传代码交付压力,当时求快就近就熟,当时求稳总存在一些不那么理想的代码:技术栈落后,甚至强行混用多种技术栈耦合混乱,不敢动,
5、牵一发何止动全身重构不彻底,重构-烂尾,换个姿势重构-又烂尾而要对这些代码进行彻底重构的话,最大的问题是很难有充裕的资源去大刀阔斧地一步到位,在逐步重构的同时,既要确保中间版本能够平滑过渡,同时还要持续交付新特性:In order to avoid the perils of a full rewrite, wed much prefer to strangle the old applicationpiece by piece, and in the meantime continue to deliver new features to our customers withoutbeing
6、 weighed down by the monolith.所以,为了实施渐进式重构,我们需要一种增量升级的能力,先让新旧代码和谐共存,再逐步转化旧代四,直到整个重构完成这种增量升级的能力意味着我们能够对产品功能进行低风险的局部替换,包括升级依赖项、更替架构、UI改版等。另一方面,也带来了技术选型上的灵活性,有助于新技术、新交互模式的实验性试错3 .独立部署独立部署的能力在微前端体系中至关重耍,能够缩小变更范围,进而降低相关风险因此,每个微前端都应具备有自己的持续交付流水线(包括构建、测试并部署到生产环境),并且要能独立部署,不必过多考虑其它代码库和交付流水线的当前状态:就算旧的系统是按固定周
7、期季度发布或手动发布的,甚至隔壁团队误发布了一个半成品或有问题的特性也无关紧要。也就是说,如果一个微前端已经准备好发布了,它就应该随时可发布,并且只由开发维护它的团队来定Source controlBuild and test pipelineMicro frontend AMicro frontend BMicro frontend CP.S.甚至还可以结合BFF模式实现更进一步的独立:DownstreamserviceDownstreamservice. or they might callthrough to shareddownstream serviceBFFs might ownt
8、heir own database.4 .团队自治除代码库及发布周期上的解耦之外,微前端还有助于形成完全独立的团队,由不同团队各自负责一块产品功能从构思到发布的整个过程,团队能够完全拥有为客户提供价值所需的一切,从而快速高效地运转为此,应该围绕业务功能纵向组建团队,而不是基于技术职能划分。最简单的,可以根据最终用户所能看到的内容来划分,比如将应用中的每个页面作为一个微前端,并交给一个团队全权负责。与基于技术职能或横向关注点(如样式、表单、校验等)组织的团队相比,这种方式能够提升团队工作的凝聚力Team A ownsMicro frontendTeam B ownsMicro frontend
9、BTeam C ownsMicro frontend C3 product-oriented, Hverticar teams 夕三.实现方案实现上,关键问题在于: 多个Bundle如何集成? 子应用之间怎样隔离影响? 公共资源如何复用? 子应用间怎样通信? 如何测试?1 . 多Bundle集成微前端架构中一般会有个容器应用(containerapplication)将各子应用集成起来,职贡如卜.:渲染公共的页面元素,比如header、footer解决横切关注点(cross-cuttingconcerns),如身份验证和导航将各个微前端整合到一个页面上,并控制微前端的渲染区域和时机集成方式分为
10、3类:服务端集成:如SSR拼装模板构建时集成:如Code Splitting运行时集成:如通过iframe、JS、Web Components等方式服务端集成服务端集成的关键在于如何保证各部分模板(各个微前端)能够独立发布,必耍的话,甚至可以在服务端也建立一套与前端相对应的结构:UsersbrowserRequestindex htmlContoinerapp serverAssembles templates andfragments into o pageRequest relevantHTML fragmentBrowsemicro frontendserver1 Order micro
11、 frontend知乎鳏想轻扬每个子服务负责泊染并服务于对应的微前端,主服务向各个子服务发起请求2 .构建时集成常见的构建时集成方式是将子应用发布成独立的npm包,共同作为主应用的依赖项,构建生成一个供部署的JS Bundle然而,构建时集成最大的问题是会在发布阶段造成耦合,任何一个子应用有变更,都要整个重新编译,意味着对于产品局部的小改动也要发布一个新版本,因此,不推荐这种方式3 .运行时集成将集成时机从构建时推迟到运行时,就能避免发布阶段的耦合。常见的运行时集成方式有:iframeJS:比如前端路由Web Components虽然直觉上用iframe好像不太好(性能、通信成本等),但在这里
12、确实是个合理选项,因为iframe无疑是最简单的方式,还天然支持样式隔离以及全局变量隔离但这种原生的隔离性,意味着很难把应用的各个部分联系到一起,路由控制、历史栈管理、深度链接(deep-linking)、响应式布局等都变得异常复杂,因而限制了 iframe方案的灵活性另一种最常见的方式是前端路由,每个子应用暴露出渲染函数,主应用在启动时加载各个子应用的独立Bundle,之后根据路由规则渲染相应的子应用。H前看来,是最灵活的方式还有一种类似的方式是Web Components,将每个子应用封装成自定义HTML兀素(而不是前端路由方案中的渲染函数),以获得Shadow DOM带来的样式隔离等好处
13、4 .影响隔离子应用之间,以及子应用与主应用间的样式、作用域隔离是必须要考虑的问题,常见解决方案如下:样式隔离:开发规范(如BEM)、CSS预处理(如SASS)、模块定义(如CSS Module).用JS来写 用SS-in-JS)、以及shadow DOM特性作用域隔离:各种模块定义(如ES Module、AMD、Common Module、UMD)5 .资源复用资源复用对于UI 一致性和代码复用有重要意义,但并非所有的可复用资源(如组件)都必须在一开始就提出来复用,建议的做法是前期允许一定程度的冗余,各个Bundle在各自的代码库中创建组件,直到形成相对明确的组件API时再建立可供复用的公共
14、组件另一方面,资源分为以下3类:基础资源:完全不含逻辑功能的图标、标签、按钮等UI组件:含有一定UI逻辑的搜索框(如自动完成)、表格(如排序、筛选、分页)等业务组件:含有业务逻辑其中,不建议跨子应用复用.业务组件,因为会造成高度耦合,增加变更成本对于公共资源的归属和管理,一般有两种模式:公共资源归属于所有人,即没有明确归属公共资源归集中管理,由专人负责从实践经验来看,前者很容易衍变成没有明确规范,且背离技术愿景的大杂烧,而后者会造成资源创建和使用的脱节,比较推荐的模式是开源软件的管理模式:Anyone can contribute to the library, but there is a
15、custodian (a person or a team) who isresponsible for ensuring the quality, consistency, and validity of those contributions.即,所有人都能补充公共资源,但要有人(或一个团队)负责监管,以保证质量、一致性以及正确性6 .应用间通信通过自定义事件间接通信是一种避免直接耦合的常用方式,此外,React的单向数据流模型也能让依赖关系更加明确,对应到微前端中,从容器应用向子应用传递数据与回调函数另外,路由参数除了能用于分享、书签等场景外,也可以作为一种通信手段,并且具有诸多优势:其结构遵从定义明确的开放标准页面级共享,能够全局访问长度限制促使只传递必要的少量数据面向用户的,有助于依照领域建模声明式的,语义上更通用(this is where we are, rather than please do