了解什么是微前端

做为前端开发人员,这些年来你一直在开发单体应用,即便你已经知道这是一个很差的作法。 您将代码划分为组件,使用 requireimport 并将package.json中定义的npm包或已安装的子git仓库添加到项目中,但最终构建了一个总体。 是时候改变它了。html

为何你的代码是一个单体?

除了已经实现了微前端的应用以外,全部前端应用本质上都是单一的应用。 缘由是若是您正在使用 React 库进行开发,而且若是您有两个团队,则两个团队都应该使用相同的React 库,而且两个团队应该在部署时保持同步,而且在代码合并期间始终会发生冲突。 它们没有彻底分离,极可能它们维护着相同的仓库并具备相同的构建系统。 单体应用的退出被标志为微服务的出现。 可是它适用于后端!😱前端

什么是微服务?

对于微服务,通常而言最简单的解释是,它是一种开发技术,容许开发人员为平台的不一样部分进行独立部署,而不会损害其余部分。 独立部署的能力容许他们构建孤立或松散耦合的服务。 为了使这个体系结构更稳定,有一些规则要遵循,能够总结以下:每一个服务应该只有一个任务,它应该很小。 因此负责这项服务的团队应该很小。 关于团队和项目的规模,James Lewis 和 Martin Fowler 在互联网上作出的最酷解释之一以下:git

在咱们与微服务从业者的对话中,咱们看到了一系列服务规模。 报道的最大规模遵循亚马逊关于Two Pizza Team的概念(即整个团队能够由两个比萨饼供给),意味着不超过十几我的。 在规模较小的规模上,咱们已经看到了一个由六人组成的团队支持六项服务的设置。web

我画了一个简单的草图,为总体和微服务提供了直观的解释:数据库

从上图能够理解,微服务中的每一个服务都是一个独立的应用,除了UI。 UI仍然是一体的! 当一个团队处理全部服务而且公司正在扩展时,前端团队将开始苦苦挣扎而且没法跟上它,这是这种架构的瓶颈。npm

除了瓶颈以外,这种架构也会致使一些组织问题。 假设公司正在发展并将采用须要 跨职能 小团队的敏捷开发方法。 在这个常见的例子中,产品全部者天然会开始将故事定义为前端和后端任务,而 跨职能 团队将永远不会成为真正的 跨职能 部门。 这将是一个浅薄的泡沫,看起来像一个敏捷的团队,但它将在内部分开。 关于管理这种团队的更多信息将是一项很是重要的工做。 在每一个计划中,若是有足够的前端任务或者sprint中有足够的后端任务,则会有一个问题。 为了解决这里描述的全部问题和许多其余问题,几年前出现了微前端的想法而且开始迅速普及。json

解决微服务中的瓶颈问题:Micro Frontends🎉

解决方案实际上很是明显,采用了多年来为后端服务工做的相同原则:将前端总体划分为小的UI片断。 但UI与服务并不十分类似,它是最终用户与产品之间的接口,应该是一致且无缝的。 更重要的是,在单页面应用时代,整个应用在客户端的浏览器上运行。 它们再也不是简单的HTML文件,相反,它们是复杂的软件,达到了很是复杂的水平。 如今我以为微型前端的定义是必要的:后端

Micro Frontends背后的想法是将网站或Web应用视为独立团队拥有的功能组合。 每一个团队都有一个独特的业务或任务领域,作他们关注和专一的事情。团队是跨职能的,从数据库到用户界面开发端到端的功能。(micro-frontends.org浏览器

根据我迄今为止的经验,对于许多公司来讲,直接采用上面提出的架构真的很难。 许多其余人都有巨大的遗留负担,这使他们没法迁移到新的架构。 出于这个缘由,更柔软的中间解决方案更加灵活,易于采用和安全迁移相当重要。 在更详细地概述了体系结构后,我将尝试提供一些体系结构的洞察,该体系结构确认了上述提议并容许更灵活的方式。 在深刻了解细节以前,我须要创建一些术语。安全

总体结构和一些术语

让咱们假设咱们经过业务功能垂直划分总体应用结构。 咱们最终会获得几个较小的应用,它们与单体应用具备相同的结构。 可是若是咱们在全部这些小型单体应用之上添加一个特殊应用,用户将与这个新应用进行通讯,它将把每一个小应用的旧单体UI组合成一个。 这个新图层能够命名为拼接图层,由于它从每一个微服务中获取生成的UI部件,并为最终用户组合成一个无缝 UI,这将是微前端的最直接实现🤩

为了更好地理解,我将每一个小型单体应用称为微应用,由于它们都是独立的应用,而不只仅是微服务,它们都有UI部件,每一个都表明端到端的业务功能。

众所周知,今天的前端生态系统功能多样,并且很是复杂。 所以,当实现真正的产品时,这种直接的解决方案还不够。

要解决的问题

虽然这篇文章只是一个想法,但我开始使用Reddit讨论这个想法。 感谢社区和他们的回复,我能够列出一些须要解决的问题,我将尝试逐一描述。

当咱们拥有一个彻底独立的独立微应用时,如何建立无缝且一致的UI体验?

好吧,这个问题没有灵丹妙药的答案,但其中一个想法是建立一个共享的UI库,它也是一个独立的微应用。 经过这种方式,全部其余微应用将依赖于共享的UI库微应用。 在这种状况下,咱们刚刚建立了一个共享依赖项,咱们就杀死了独立微应用的想法。

另外一个想法是在根级共享CSS自定义变量( CSS custom variables )。 此解决方案的优点在于应用之间的全局可配置主题。

或者咱们能够简单地在应用团队之间共享一些SASS变量和混合。 这种方法的缺点是UI元素的重复实现,而且应该对全部微应用始终检查和验证相似元素的设计的完整性。

咱们如何确保一个团队不会覆盖另外一个团队编写的CSS?

一种解决方案是经过CSS选择器名称进行CSS定义,这些名称由微应用名称精心选择。 经过将该范围任务放在拼接层上将减小开发开销,但会增长拼接层的责任。

另外一种解决方案能够是强制每一个微应用成为自定义Web组件(custom web component)。 这个解决方案的优势是浏览器完成了范围设计,但须要付出代价:使用shadow DOM进行服务器端渲染几乎是不可能的。 此外,自定义元素没有100%的浏览器支持,特别是IE。

咱们应该如何在微应用之间共享全局信息?

这个问题指出了关于这个主题的最关注的问题之一,但解决方案很是简单:HTML 5具备至关强大的功能,大多数前端开发人员都不知道。 例如,自定义事件(custom events) 就是其中之一,它是在微应用中共享信息的解决方案。

或者,任何共享的pub-sub实现或T39可观察的实现均可以实现。 若是咱们想要一个更复杂的全局状态处理程序,咱们能够实现共享的微型Redux,经过这种方式咱们能够实现更多的相应式架构。

若是全部微应用都是独立应用,咱们如何进行客户端路由?

这个问题取决于设计的每一个实现, 全部主要的现代框架都经过使用浏览器历史状态在客户端提供强大的路由机制, 问题在于哪一个应用负责路由以及什么时候。

我目前的实用方法是建立一个共享客户端路由器,它只负责顶级路由,其他路由器属于相应的微应用。 假设咱们有 /content/:id 路由定义。 共享路由器将解析 /content,已解析的路由将传递到ContentMicroApp。 ContentMicroApp是一个独立的服务器,它将仅使用 /:id 进行调用。

咱们必须是服务器端渲染,可是有可能使用微前端吗?

服务器端呈现是一个棘手的问题。 若是你正在考虑iframes缝合微应用而后忘记服务器端渲染。 一样,拼接任务的Web组件也不比iframe强大。 可是,若是每一个微应用可以在服务器端呈现其内容,那么拼接层将仅负责链接服务器端的HTML片断。

与传统环境集成相当重要! 可是怎么样?

为了整合遗留系统,我想描述我本身的策略,我称之为“ 渐进式入侵 ”。

首先,咱们必须实现拼接层,它应该具备透明代理的功能。 而后咱们能够经过声明一个通配符路径将遗留系统定义为微应用LegacyMicroApp 。 所以,全部流量都将到达拼接层,并将透明地代理到旧系统,由于咱们尚未任何其余微应用。

下一步将是咱们的 第一次逐步入侵 :咱们将从LegacyMicroApp中删除主要导航并用依赖项替换它。 这种依赖关系将是一个使用闪亮的新技术实现的微应用NavigationMicroApp

如今,拼接层将每一个路径解析为 Legacy Micro App ,它将依赖关系解析为 Navigation MicroApp ,并经过链接这两个来为它们提供服务。

而后经过主导航遵循相同的模式来为引导下一步。

而后咱们将继续从Legacy MicroApp中获取逐步重复以上操做,直到没有任何遗漏。

如何编排客户端,这样咱们每次都不须要从新加载页面?

拼接层解决了服务器端的问题,但没有解决客户端问题。 在客户端,在将已粘贴的片断做为无缝HTML加载后,咱们不须要每次在URL更改时加载全部部分。 所以,咱们必须有一些异步加载片断的机制。 但问题是,这些片断可能有一些依赖关系,这些依赖关系须要在客户端解决。 这意味着微前端解决方案应提供加载微应用的机制,以及依赖注入的一些机制。


根据上述问题和可能的解决方案,我能够总结如下主题下的全部内容:

客户端

  • 编排
  • 路由
  • 隔离微应用
  • 应用之间通讯
  • 微应用UI之间的一致性

服务端

  • 服务端渲染
  • 路由
  • 依赖管理

灵活、强大而简单的架构

因此,这篇文章仍是很值得期待的! 微前端架构的基本要素和要求终于显现!

在这些要求和关注的指导下,我开始开发一种名为microfe的解决方案。 😎在这里,我将经过抽象的方式强调其主要组件来描述该项目的架构目标。

它很容易从客户端开始,它有三个独立的主干结构:AppsManager, Loader, Router 和一个额外的MicroAppStore。

AppsManager

AppsManager 是客户端微应用编排的核心。 AppsManager的主要功能是建立依赖关系树。 当解决了微应用的全部依赖关系时,它会实例化微应用。

Loader

客户端微应用编排的另外一个重要部分是Loader。 加载器的责任是从服务器端获取未解析的微应用。

Router

为了解决客户端路由问题,我将 Router 引入了 microfe。 与常见的客户端路由器不一样,microf 的功能有限,它不解析页面而是微应用。 假设咱们有一个URL /content/detail/13 和一个ContentMicroApp。 在这种状况下,microfe 将URL解析为 /content/,它将调用ContentMicroApp /detail/13 URL部分。

MicroAppStore

为了解决微应用到微应用客户端的通讯,我将MicroAppStore引入了 microfe。 它具备与Redux库相似的功能,区别在于:它对异步数据结构更改和reducer 声明更灵活。


服务器端部分在实现上可能稍微复杂一些,但结构更简单。 它只包含两个主要部分 StitchingServer 和许多MicroAppServer。

MicroAppServer

MicroAppServer 的最小功能能够归纳为 initserve。

虽然 MicroAppServer 首先启动它应该作的是使用 微应用声明 调用 SticthingServer 注册端点,该声明定义了 MicroAppServer 的微应用 依赖关系, 类型URL架构。 我认为没有必要说起服务功能,由于没有什么特别之处。

StitchingServer

StitchingServerMicroAppServers 提供注册端点。 当 MicroAppServer 将本身注册到 StichingServer 时,StichingServer 会记录MicroAppServer 的声明。

稍后,StitchingServer 使用声明从请求的URL解析 MicroAppServers。

解析M icroAppServer 及其全部依赖项后,CSS,JS和HTML中的全部相对路径都将以相关的 MicroAppServer 公共URL为前缀。 另一步是为CSS选择器添加一个惟一的 MicroAppServer 标识符,以防止客户端的微应用之间发生冲突。

而后 StitchingServer 的主要职责就是:从全部收集的部分组成并返回一个无缝的HTML页面。

其余实现一览

甚至在2016年被称为微前端以前,许多大公司都试图经过 BigPipe 来解决Facebook等相似问题。 现在这个想法正在得到验证。 不一样规模的公司对该主题感兴趣并投入时间和金钱。 例如,Zalando开源了其名为Project Mosaic的解决方案。 我能够说,微型和 Project Mosaic.遵循相似的方法,但有一些重要的区别。 虽然microfe采用彻底分散的路由定义来加强每一个微应用的独立性,但Project Mosaic更喜欢每条路径的集中路由定义和布局定义。 经过这种方式,Project Mosaic能够实现轻松的A/B测试和动态布局生成。

对于该主题还有一些其余方法,例如使用iframe做为拼接层,这显然不是在服务器端而是在客户端。 这是一个很是简单的解决方案,不须要太多的服务器结构和DevOps参与。 这项工做只能由前端团队完成,所以能够减轻公司的组织负担,同时下降成本。

已经有一个框架叫作 single-spa 该项目依赖于每一个应用的命名约定来解析和加载微应用。 容易掌握想法并遵循模式。 所以,在您本身的本地环境中尝试该想法多是一个很好的初步介绍。 可是项目的缺点是你必须以特定的方式构建每一个微应用,以便他们能够很好地使用框架。

最后的想法

我相信微前端话题会更频繁地讨论。 若是该主题可以引发愈来愈多公司的关注,它将成为大型团队的事实发展方式。 在不久的未来,任何前端开发人员均可以在这个架构上掌握一些看法和经验,这真的颇有用。

考虑贡献

我正在大力尝试微前端,在个人脑海中有一个崇高的目标:建立一个微框架框架,能够解决大多数问题,而不会影响性能,易于开发和可测试性。 若是您有任何明智的想法,请不要犹豫,访问个人repo,打开问题或经过下面的评论或 Twitter DM 与我联系。 我会在那里帮助你!🙂

翻译:Vincent.W
原文:Understanding Micro Frontends

相关文章
相关标签/搜索