微前端架构是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。
本文将继 《实施微前端的六种方式(上):三种借助路由微服务化前端应用 》后,介绍其中的三种方式。
组合式集成,即通过软件工程的方式在构建前、构建时、构建后等步骤中,对应用进行一步的拆分,并重新组合。
从这种定义上来看,它可能算不上并不是一种微前端——它可以满足了微前端的三个要素,即:独立运行、独立开发、独立部署。但是,配合上前端框架的组件 Lazyload 功能——即在需要的时候,才加载对应的业务组件或应用,它看上去就是一个微前端应用。
与此同时,由于所有的依赖、Pollyfill 已经尽可能地在首次加载了,CSS 样式也不需要重复加载。
常见的方式有:
应用间的关系如下图所示(其忽略图中的 “前端微服务化”):
这种方式看上去相当的理想,即能满足多个团队并行开发,又能构建出适合的交付物。
但是,首先它有一个严重的限制:必须使用同一个框架。对于多数团队来说,这并不是问题。采用微服务的团队里,也不会因为微服务这一个前端,来使用不同的语言和技术来开发。当然了,如果要使用别的框架,也不是问题,我们只需要结合上一步中的自制框架兼容应用就可以满足我们的需求。
其次,采用这种方式还有一个限制,那就是:规范!*规范!*规范!。在采用这种方案时,我们需要:
因此,这种方式看起来更像是一个软件工程问题。
现在,我们已经有了四种方案,每个方案都有自己的利弊。显然,结合起来会是一种更理想的做法。
考虑到现有及常用的技术的局限性问题,让我们再次将目光放得长远一些。
在学习 Web Components 开发微前端架构的过程中,我尝试去写了我自己的 Web Components 框架:oan。在添加了一些基本的 Web 前端框架的功能之后,我发现这项技术特别适合于作为微前端的基石。
Web Components 是一套不同的技术,允许您创建可重用的定制元素(它们的功能封装在您的代码之外)并且在您的 Web 应用中使用它们。
它主要由四项技术组件:
<template>
和 <slot>
元素,用于编写不在页面中显示的标记模板。每个组件由 link
标签引入:
<link rel="import" href="components/di-li.html">
<link rel="import" href="components/d-header.html">
随后,在各自的 HTML 文件里,创建相应的组件元素,编写相应的组件逻辑。一个典型的 Web Components 应用架构如下图所示:
可以看到这边方式与我们上面使用 iframe 的方式很相似,组件拥有自己独立的 Scripts
和 Styles
,以及对应的用于单独部署组件的域名。然而它并没有想象中的那么美好,要直接使用纯 Web Components 来构建前端应用的难度有:
Web Components 中的 ShadowDOM 更像是新一代的前端 DOM 容器。而遗憾的是并不是所有的浏览器,都可以完全支持 Web Components。
Web Components 离现在的我们太远,可是结合 Web Components 来构建前端应用,则更是一种面向未来演进的架构。或者说在未来的时候,我们可以开始采用这种方式来构建我们的应用。好在,已经有框架在打造这种可能性。
就当前而言,有两种方式可以结合 Web Components 来构建微前端应用:
前者是一种组件式的方式,或者则像是在迁移未来的 “遗留系统” 到未来的架构上。
现有的 Web 框架已经有一些可以支持 Web Components 的形式,诸如 Angular 支持的 createCustomElement,就可以实现一个 Web Components 形式的组件:
platformBrowser()
.bootstrapModuleFactory(MyPopupModuleNgFactory)
.then(({injector}) => {
const MyPopupElement = createCustomElement(MyPopup, {injector});
customElements.define(‘my-popup’, MyPopupElement);
});
在未来,将有更多的框架可以使用类似这样的形式,集成到 Web Components 应用中。
另外一种方式,则是类似于 Stencil 的形式,将组件直接构建成 Web Components 形式的组件,随后在对应的诸如,如 React 或者 Angular 中直接引用。
如下是一个在 React 中引用 Stencil 生成的 Web Components 的例子:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import 'test-components/testcomponents';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
在这种情况之下,我们就可以构建出独立于框架的组件。
同样的 Stencil 仍然也只是支持最近的一些浏览器,比如:Chrome、Safari、Firefox、Edge 和 IE11
复合型,对就是上面的几个类别中,随便挑几种组合到一起。
我就不废话了。
围观我的Github Idea墙, 也许,你会遇到心仪的项目