微前端:前端的微服务
微服务是构建小型、自主、可独立工作的团队的流行方式。然而,微服务本质上只能在后端工作。即使采用最佳的微服务架构,前端开发仍然需要高度的相互依赖,这会带来耦合和通信开销,从而降低每个人的工作效率。
我们能否将微服务架构模式应用于前端?答案是肯定的。Netflix 、Zalando和Capital One等公司已将这种模式推向前台,为微前端奠定了基础。本文将探讨微前端、其优缺点以及它与传统微服务的区别。
前端微服务
微前端就是将微服务方法引入前端。换句话说,微前端由不同团队拥有的组件组成,这些组件可以独立部署。这些组件的组合旨在打造一致的用户体验。
使用微前端,没有哪个团队能够完全掌控 UI。相反,每个团队都拥有一部分屏幕、页面或内容。例如,一个团队可能负责搜索框,而另一个团队可能负责根据用户喜好编写建议。其他团队可能负责音乐播放器、播放列表管理或结算页面的渲染。我们增加了复杂性,但团队也因此获得了更大的自主权。
微前端的优势与挑战
微前端具有与微服务类似的优势。也就是说,我们可以通过将前端代码拆分成独立的部分,由不同的团队负责,从而扩展开发规模。与微服务一样,每个功能都可以随时独立发布,几乎无需协调。这可以提高更新频率。
垂直团队
微前端支持创建垂直团队,这意味着全栈开发人员团队可以同时拥有后端和前端的功能。
持续部署组件
微前端的每个部分都是一个可部署单元。这使得团队可以发布自己的更改,而无需等待发布列车或依赖其他团队完成工作。最终结果是前端可以每天更新多次。
微前端设计的挑战
微前端的主要挑战是创建快速且响应迅速的客户端。我们绝不能忽视前端所处的内存、CPU 和网络环境有限这一事实,否则最终会导致 UI 运行缓慢。
流畅的用户界面对于产品的成功至关重要。最近的一项调查指出,“加载时间为 1 秒的网站的转化率比加载时间为 5 秒的网站高出 3 倍”。用户每等待一秒,就意味着金钱的流失。
除了微服务面临的所有挑战之外,微前端设计还带来了一些问题:
- 隔离性:每个团队的代码最终必须共存于同一个浏览器。我们必须谨慎地隔离各个模块,以避免代码或代码风格冲突。
- 共享资源:为了避免重复并保持前端精简,组件应尽可能共享资产和库,这可能会产生不良的耦合。
- 可访问性:过度依赖 JavaScript 来呈现页面会对可访问性产生负面影响。
- 样式:当 UI 由多个团队开发的组件组成时,保持一致的外观会变得更加复杂。细微的风格差异都会让人感到不协调。
协调:由于存在如此多的移动部件,API 需要定义明确且稳定。团队必须协调微前端中不同组件之间以及与后端微服务之间的通信方式。
构建微前端的原则
有两种互补的方法可以从单独的微前端组件渲染统一的 UI:服务器端渲染和客户端渲染。
服务器端渲染(SSR)
服务器端渲染提供更快的性能和更易于访问的内容。服务器渲染是快速提供内容的良好替代方案,尤其是在低端手机等低功耗设备上。当 JavaScript 被禁用时,它也是一个合适的回退模式。
我们有几种执行 SSR 的方法:
- 服务器端包含(SSI):是一种由 Web 服务器执行的简单脚本语言。该语言使用指令将 HTML 片段构建成完整的页面。这些片段可能来自其他文件或程序的响应。所有主流 Web 服务器都支持 SSI,包括 Apache、Nginx 和 IIS。
- iframe:古老的 iframe 功能允许我们在页面上嵌入任意 HTML 内容。
- 边缘侧包含(ESI):SSI 的更现代替代方案。ESI 可以处理变量、条件语句,并支持更强大的错误处理功能。Varnish 等缓存HTTP 服务器支持 ESI 。
例如,我们可以使用 SSI 从 HTML 渲染页面,如下所示:
<div>
<!--#include virtual="/hello-world" -->
</div>
该virtual
关键字使 Web 服务器从 URL 或 CGI 程序请求内容。在我们的例子中,我们需要设置 Web 服务器,使其根据路径/hello-world
使用合适的片段来响应请求:
<h1>Hello World!</h1>
许多 Web 框架都使用 SSR 来渲染首屏。此外,还有一些有趣的 SSR 专用实用程序,例如compoxure、nodesi和tail。
客户端渲染(CSR)
客户端渲染通过从微服务获取数据并操作 DOM 来在用户浏览器中构建页面。大多数 Web 框架都使用某种形式的 CSR 来提升用户体验。
我们编写松耦合组件的主要工具是自定义元素。自定义元素是 HTML 标准的一部分。它们允许我们创建新的 HTML 标签,并为其附加逻辑和行为。
自定义元素使用 JavaScript 在页面上动态安装和卸载:
// hello-world-component.js
class HelloWorld extends HTMLElement {
connectedCallback() {
this.innerHTML = `<h1>Hello world</h1>`;
}
}
customElements.define('hello-world', HelloWorld);
一旦定义,我们就可以像任何其他 HTML 标签一样使用新元素:
<hello-world></hello-world>
在示例中,整个页面将包含一个脚本标签来获取 JavaScript 组件:
<!doctype html>
<head>
<meta charset="utf-8">
<title>Microservice Example</title>
</head>
<body>
<script src="./hello-world-component.js" async></script>
<hello-world></hello-world>
</body>
虽然大多数前端框架都可以用于微前端,但有些框架是专门为微前端设计的:
- Piral :实现了称为Pilets 的独立组件。Pilets 是捆绑内容和行为的模块。
- Ragu:一个框架中的框架。它允许我们将任何框架中编写的代码嵌入到小部件中。
- 单一 SPA:一个元框架,使用 React、Angular、Ember 等任意前端框架组合来拼凑 UI。
- Frint:另一个用于构建基于组件的应用程序的模块化框架。与 React、Vue 和 Preact 集成。
- Module Federation:一个 WebPack 插件,用于通过打包单独的构建来创建单页应用程序 (SPA)。这些构建可以独立开发。
结论
切换到微前端架构可以赋予我们的开发团队更多自主权,从而加速开发。然而,适用于微服务的注意事项也同样适用于微前端。我们需要一个经过验证的设计,这意味着微前端并不适合新建项目。
新项目最好采用传统模式,例如由单个团队管理的单页应用程序 (SPA)。只有当前端经受住了时间的考验,我们才能将微前端视为未来的发展方向。
鏂囩珷鏉ユ簮锛�https://dev.to/semaphore/microfrontends-microservices-for-the-frontend-4la4