❝
本篇文章全文约 1.5 万字,目的是系统化地介绍微前端及其核心技术,并介绍了什么是微前端以及为什么我们需要它。我们还讨论了在众多微前端框架中如何选择适合自己系统的框架,并分享了一些业界使用微前端的实践案例。最后,我们提到了微前端目前存在的一些局限性和争议点。总之,希望这篇文章能为大家提供有用的信息。
❞
「初期的静态网页阶段」
在早期的前端开发中,网页主要由 HTML (HyperText Markup Language) 构建,每个页面都是一个静态的 HTML 文件。这些页面通常包含基本的文本、链接和图片,用户与之交互的方式非常有限。这时期的网站主要是信息展示,交互性较弱。
「动态网页和 JavaScript 的出现」
随着 JavaScript 的出现,前端开发开始进入新的阶段。JavaScript 为浏览器提供了执行代码的能力,使得网页变得更加动态和交互性强。例如,用户可以通过点击按钮来改变网页内容,或者通过表单输入数据。这一阶段的前端开发开始了前后端交互的初步实现。
「AJAX 和 Web 2.0 阶段」
Web 2.0 标志着网页开发的又一次重大变革。AJAX(Asynchronous JavaScript and XML)技术的出现使得网页可以在不刷新整个页面的情况下从服务器获取数据。这意味着网页可以实时更新,用户体验大大提升。此阶段的网站开始偏向于服务和应用,而非单纯的信息展示。
「单页应用(SPA)和现代前端框架」
随着 AngularJS、React、Vue 等现代前端框架的出现,前端开发进入了单页应用(SPA)的时代。在这个阶段,整个 Web 应用只需要加载一次,之后所有的操作都在客户端进行,只有当需要从服务器获取或更新数据时,才会发出请求。这大大提升了用户体验,使得 Web 应用的表现更接近桌面应用。
「微前端的崭露头角」
微前端是近年来前端开发的新趋势,它是微服务概念在前端的应用。在微前端的架构下,一个大型的前端应用可以被拆分成多个小的、独立运行的应用,这些小应用可以独立开发、独立部署、独立运行。微前端的出现使得大型前端项目的开发和管理变得更加灵活和高效。
微前端是一种新兴的前端架构模式,其核心理念在于将一个庞大且单一的前端应用拆解为一系列小型、独立的微应用。这些微应用各自作为一个独立的前端应用,拥有自己的开发和技术栈,可以由不同的团队独立开发、部署和维护。这种拆分带来了三大特性:应用自治,单一职责以及技术栈无关性。微前端的设计目标在于提高前端应用的可维护性和可扩展性,以便让开发团队能更加敏捷地开发和部署应用程序。
微前端模式图
微前端的实现可以通过两种主要模式进行,即基座模式和自组织模式。
基座模式是一种中心化的管理模式,由一个主应用作为所有微应用的入口,负责统一管理和协调。虽然这种模式在设计上相对简单,但其通用性较低。因为在基座模式下,子应用必须遵循基座应用的规范和约定,以便与基座应用进行集成。这种强依赖性在一定程度上限制了子应用的灵活性和独立性。
相反,自组织模式则是一种去中心化的模式,系统内的各个微应用都各自拥有一个小型的基座管理功能,也就是说,每个应用都可以作为基座。这种模式下,应用之间平等且不存在互相依赖,虽然设计起来较为复杂,实现起来也不太方便,但是其通用性较高。
「优点」「缺点」「基座模式」设计难度较小,中心化管理带来的协调性和一致性较强通用性较低,子应用必须遵循基座应用的规范和约定,限制了子应用的灵活性和独立性「自组织模式」应用之间平等,不存在互相依赖,具有较高的通用性和灵活性设计和实现难度较大,需要编写和维护较多的重复代码
微前端的具体实现方法有很多种,例如可以通过 iframe、JavaScript 模块、Web Components 等方式来实现。这些实现方式都能帮助开发团队将应用程序分解为更小、更易于维护的部分,并且每个部分都可以独立地进行开发、测试和部署。这样,不同的团队或开发者可以专注于自己负责的部分,并独立地进行开发和部署,从而提高整个团队的协作效率和开发速度。
微前端已经成为现代前端开发中的一个重要发展方向,它吸引了越来越多的企业和开发者的关注。微前端不仅有助于团队更敏捷地开发和部署应用,同时也有利于提高应用程序的可维护性和可扩展性。随着前端技术的不断发展和应用场景的变化,微前端将持续发挥其重要作用,成为前端开发中不可或缺的一部分。
微前端架构的设计原则是将大型前端应用分解成一组较小的、独立运行的微应用。这些微应用可以独立开发、部署,并且有自己的技术栈,但最终它们将被整合到一起,为用户提供一致的体验。下面是微前端的一些核心理念:
这些原则共同构成了微前端的核心理念,旨在支持快速的迭代,易于维护,同时保证用户体验的一致性和流畅性。微前端实际上是一种将微服务的理念扩展到前端开发的方法,它解决了单体应用规模扩大后难以维护和升级的问题,同时避免了微服务可能带来的复杂性。
了解当前已经有的微前端框架,可以帮助开发人员选择适合自己项目的技术方案。在详细讨论微前端的关键技术之前,我们将介绍一些比较常见的微前端框架,比如: Single-SPA、qiankun、无界、microapp 等等。
框架名称所属方「描述」「沙箱机制」「路由分发式」原始将不同的路由分发到不同的微应用的策略,使其看起来是一个整体。无「iframe」原生使用 iframe 进行微应用的隔离和集成。有天然的沙箱环境,可以隔离全局对象、样式等「single-spa」社区一个用于将多个独立开发的应用整合到一个页面的 JavaScript 微前端框架。
无「qiankun」蚂蚁基于 Single-SPA,提供简单易用的 API、多种通信和协调机制。有基于 proxy 实现的沙箱机制「icestark」阿里icestark 是面向大型系统的微前端解决方案,适用于后台系统分散、体验差异大、开发成本高、需要接入二方/三方模块的场景。有基于 proxy 实现的沙箱机制「micro-app」京东基于类 WebComponent 进行渲染,从组件化的思维实现微前端。有基于 proxy 实现的沙箱机制「wujie」腾讯基于组件化的思维实现微前端,旨在降低上手难度、提升工作效率。基于 iframe 的沙箱机制
「原理」
路由分发式微前端通过路由将不同的业务分发到各个独立的前端应用上。这一原理通常可以通过 HTTP 服务器的反向代理来实现,或者可以借助应用框架自带的路由系统来解决。例如,下面的配置就展示了如何用 Nginx 服务器的反向代理来将请求分发到不同的微应用:
http { server { listen 80; server_name xxx; location /api/ { proxy_pass http://192.168.0.3:8000/api; } location /web/admin { proxy_pass http://192.168.0.1/pc/app1; } location /web/notifications { proxy_pass http://192.168.0.2/pc/app1; } location / { proxy_pass /; } }}
「特点」
「优点」
「缺点」
「原理」
使用 iframe 标签来嵌入和隔离不同的微应用,实现微前端的设计原则。每个子应用都在其自己的 iframe 容器中运行,与其他子应用完全隔离。
「优点」
「缺点」
single-spa[1]是最初引入的微前端 JavaScript 框架之一,以其对多种前端技术栈的兼容性而闻名。
「原理」
single-spa 的核心是一种运行时协议,这个协议定义了主应用与子应用之间的交互规则。具体来说,这个协议规定了主应用如何配置不同的子应用,以及子应用在不同情况下应执行的生命周期钩子。这使得主应用能精确地感知和控制每个子应用的挂载和卸载时机。
「优点」
「缺点」
单独探讨某一微前端框架的优点,很难脱离 single-spa 的影响。因此 single-spa 存在的优点下面的框架都基本存在,这里便不一一重复。
qiankun[2]是蚂蚁金服前端团队基于 single-spa 开发的微前端框架,它提供了更完善、更先进的功能和解决方案,以帮助开发者更轻松地构建微前端应用。
「原理」
「优点」
「缺点」
icestark[3]是飞冰团队为大型系统提供的微前端解决方案。为了方便 icejs 应用快速接入微前端解决方案,飞冰团队还专门提供了一个名为 build-plugin-icestark 的独立插件。
「原理」
「优点」
「缺点」
micro-app[4]是京东零售推出的一款微前端框架。该框架以类 WebComponent 的方式进行渲染,采用了组件化的思维来实现微前端,目的在于降低上手难度并提升开发效率。
「原理」
micro-app 借鉴了 WebComponent 的思想,它通过 CustomElement 结合自定义的 Shadow DOM,将微前端封装成一个类 WebComponent 组件,从而实现微前端的组件化渲染。
「优点」
「缺点」
wujie[5]是腾讯推出的一款微前端解决方案,主要基于组件化的思维实现微前端,旨在降低上手难度并提升工作效率。
「原理」
Wujie 框架的核心技术是基于 WebComponent 容器与 iframe 沙箱来实现微前端。
「优点」
「缺点」
在选择微前端框架时,可以参考上述的分析,并结合框架的最新更新时间、社区活跃度等因素,以找到最适合自己需求的前端框架。以下是一些常见微前端框架的对比:
「框架」「git stars」「代码最近更新时间」「社区活跃度」「接入成本」「路由分发式」无 git无无高「iframe」无 git无无高「single-spa」12.6k[6]2023-08-09较高高「qiankun」14.8k[7]2023-09-07高较低「icestark」1.9k[8]2023-08-23较低较低「micro-app」4.5k[9]2023-09-08较高低「wujie」3.2k[10]2023-08-24较高低
上图更新时间截止:2023-09-10
基于以上对比,如果是「老项目」需要引入微前端架构,qiankun 可能是一个比较适合的选择。对于「初次尝试」微前端的项目,wujie 和 micro-app 也是值得考虑的选项。
虽然 single-spa 在接入成本上可能高于其他框架,但一旦掌握了 single-spa,其它框架的使用将变得相对顺利,因为 single-spa 在微前端框架中起到了概念引领者的角色。
需要注意的是,虽然 iframe 存在一些问题,但在某些特定的情况下,它仍然是一个有效的工具。例如,当需要快速将其他应用程序,如广告页,报表等仅简单嵌入到系统中时,使用 iframe 可能是一个合适的选择。
实施微前端的过程并非易事,它需要深入了解和娴熟掌握一系列关键技术,包括路由管理、全局状态管理及通信、性能优化,以及错误隔离与处理等。下面,我们将详细探讨这些关键技术:
微前端架构允许微应用独立运行,每个微应用都具有自己的路由菜单导航逻辑。这样就带来了一个问题,如何将所有微应用的菜单整合到主应用中。为解决这一挑战,我们可以采取以下三种策略:
在中心化路由管理模式下,所有微应用的路由被集中管理,由主应用维护全局路由表和菜单,并将微应用的路由信息融入到全局路由表中。在这种模式下,微应用需要通过主应用获取自己的路由信息,并依据该信息进行路由控制和导航。
「优势:」
「劣势:」
以 qiankun 框架为例,中心化路由管理的实现关键步骤如下:
// 在主应用程序中定义获取路由信息的接口function getRoutes() { // 返回全局路由表 return globalRoutes;}// 在主应用程序中注册子应用qiankun.registerMicroApps([ { name: 'my-app', entry: '//localhost:3001', container: '#my-app', activeRule: '/my-app', props: { getRoutes, // 将获取路由信息的接口传递给子应用 }, }, // ...]);
/** * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法 */export const mount: (props: any) => void = async props => { await render(); setGlobalData(props.data); setLoadGlobalFinish(true);};
在动态路由管理模式下,主应用和微应用各自维护自己的路由菜单逻辑及控制。微应用向主应用暴露自己的路由菜单数据,主应用在运行时,动态获取微应用的数据来生成自己的路由菜单。
「优势:」
「劣势:」
在 qiankun 框架中,动态路由管理模式可以通过以下步骤实现:
import { setGlobalState } from 'qiankun';const routes = [ { path: '/home', name: 'Home', component: Home, }, { path: '/about', name: 'About', component: About, },];setGlobalState({ routes,});
import { useEffect } from 'react';import { getGlobalState } from 'qiankun';const App = () => { const [routes, setRoutes] = useState([]); useEffect(() => { const routes = getGlobalState('routes') || []; setRoutes(routes); }, []); return ( <div> <ul> {routes.map((route) => ( <li key={route.path}> <Link to={route.path}>{route.name}</Link> </li>))} </ul> <hr /> <Router> {routes.map((route) => ( <Route key={route.path} path={route.path} component={route.component} /> ))} </Router> </div> );};
混合式路由管理则是中心化路由管理和动态路由管理两者的结合。主应用维护全局的路由表和菜单,微应用则维护自身的路由表和菜单。微应用的路由表和菜单信息会被主应用动态获取和整合。
「优势:」
「劣势:」
混合式路由管理的实现主要是结合了中心化路由管理和动态路由管理的实现方式,主应用需要动态地获取微应用的路由信息,并将这些信息整合到全局路由表中。
微前端作为一种新兴的设计理念,它将大型单体前端应用程序分解成多个独立运行的小型应用。在这种架构下,全局状态管理和通信是一个重要的话题。实现这个目标的方式有很多,以下是几种常见的策略:
在大多数基础场景下,微前端框架本身提供的通信方法已经能够满足需求。然而,在面临一些特殊的业务需求时,可能需要自定义通信解决方案。
接下来,我们将以 qiankun 框架提供的 actions 为例,详细解析如何实现微前端的通信。
首先,我们在主应用中注册 MicroAppStateActions 实例,并导出:
// micro-app-main/src/shared/actions.tsimport { initGlobalState, MicroAppStateActions } from "qiankun";const initialState = {};const actions: MicroAppStateActions = initGlobalState(initialState);export default actions;
然后,在注册子应用的列表中,将 actions 以 props 的形式传递给子应用:
const apps = [ { name: 'App1', entry: "http://localhost:8000", container: "#container", activeRule: '/vue', props: { actions} //向子应用传递创建的全局状态 }]
接下来,当主应用的某个组件(如 ComponentA)的数据发生变化时,我们可以通过调用 actions 的 setGlobalState 方法来通知子应用:
<template> <div> <el-button @click="handleNotification">通知子应用1</el-button> </div></template><script> import actions from "@/shared/actions"; export default { name: 'ComponentA', methods: { handleNotification() { actions.setGlobalState({message:'发送消息'}) } } }</script>
在子应用中接收消息,接受前需要先配置子应用的全局状态 Actions,并在 main.js 中注入父应用传过来的 acitons 实例:
function initMethod(state: unknown) { console.warn("state----", state);}class Actions { // 默认值为空 Action actions = { onGlobalStateChange: initMethod, setGlobalState: initMethod, }; // 设置 actions setActions(actions: unknown) { this.actions = actions; } // 映射 onGlobalStateChange(...args: any) { return this.actions.onGlobalStateChange({...args}); } // 映射 setGlobalState(...args: unknown[]) { return this.actions.setGlobalState({...args}); }}const actions = new Actions();export default actions;
在 main.js 的 mount 生命周期接收父应用传递的 actions,并注入 actions 实例
export async function mount(props) { if (props) { // 注入 actions 实例 actions.setActions(props) } render(props);}
最后,我们在子应用的 pageA.js 中监听全局状态的变化:
<script> import actions from "./actions"; export default { name: 'ComponentA', mounted(){ actions.onGlobalStateChange((state, prevState)=>{ const { message } = state console.info('接收消息:',message) }) } }</script>
至此,我们已经完成了使用 qiankun 进行微前端通信的全部步骤。这种方法的优点在于,它提供了一种跨应用的通信机制,实现了状态的共享与同步。然而,它也有一些缺点,例如在复杂的业务场景下可能需要定制化解决方案,以及可能存在的性能问题等。
总的来说,选择合适的微前端通信方案,需要根据具体的业务场景和技术栈来考量。既要考虑易用性和可维护性,也要兼顾性能和稳定性。
在微前端架构中,性能优化是一个不能忽视的重要环节。特别是在同时运行多个微应用程序的情况下,需要从多个角度对性能问题进行深入分析。以下是一些常见的性能瓶颈以及相应的优化策略:
在微前端架构中,多个独立的微应用程序可能会对首屏加载速度产生负面影响。
优化策略:
由于微前端架构涉及多个独立的微应用,因此应用间的切换可能对性能产生影响。
优化策略:
微前端架构可能会使得全局状态的管理变得复杂,从而影响性能。
优化策略:
以上只是一些可能的性能问题和优化策略。具体的优化策略可能需要根据项目的具体需求和环境进行调整。在进行性能优化时,应当牢记一条原则:不要过早优化,所有的优化活动都应该基于实际的性能问题和量化的性能指标进行。
微前端架构是一种强大的渐进式技术,它在多个不同的应用场景中都可以发挥重要作用。以下是一些微前端的典型应用场景:
微前端架构的强大之处在于其兼容性和灵活性,只有当你需要使用它时,才需要去了解和采用它。因此,面对问题时,最合适的解决方案就是最好的解决方案。
以下是一些微前端架构的实际应用案例:
以上公司通过使用微前端架构来提高应用程序的可维护性、可扩展性和开发效率,并且均取得了不错的成果和效益。
微前端的设计理念为解决大规模应用的管理问题提供了新的解决方案。然而,任何架构模型都无法适应所有的使用场景。微前端架构也不例外,它的应用也存在一些局限性和挑战,同时,也引发了一些争议。
微前端架构下,每个微应用都可能有自己的依赖和运行环境,这可能导致一些性能开销,如额外的网络请求、重复的代码、甚至重复的运行环境。对于这一问题,我们需要进行一些优化,如使用共享依赖、根据业务需求选择适当的加载策略等。
微前端架构需要对系统进行适当的拆分和组织,这可能增加了初始的构建复杂性。因此需要进行合适的架构规划和技术选型,以确保各个微前端应用之间的协作和集成顺利进行。
在微前端架构中,不同的应用程序之间需要进行跨域通信,以实现共享数据和协作。这就需要我们考虑跨域通信的安全性和效率,并选择合适的通信机制。
微前端架构中的不同微前端应用程序可能具有不同的发布和版本控制策略。管理多个应用程序的版本控制和升级过程可能变得复杂,需要确保不同版本的应用程序之间的兼容性和一致性。
部分网友的争议点:
网友 1:听说这个微前端是内卷出来的,iframe 完全可以作为代替方案。。。嗐
网友 2:一个整用多个 spa 框架实现再反向代理就已经很冗余了,如果还非要把多个框架塞到一个页面里,开发成本和维护成本和所谓的微前端应该如何取舍已经不言而喻了吧。
网友 3: 如果浏览器再出个 iframe 优化方案 ,以后是不是可以再次回归 iframe
网友 4:对小型的项目,小规模应用的场景,用 iframe 就很不错。也没必要别人上微前端,我们就是跟着用。
网友 5:纯粹为了技术而技术,根本不考虑这个沟通和协作成本的问题。。。。其实包括后端的微服务架构,又有多少项目不是为了微服务而微服务呢。
网友 6:说白了就是拿了工资需要玩出点新鲜花样好增加业绩和经验 这些东西都是后端玩剩下的 只不过搬到前端来用了 大前端才是趋势 多端统一 微前端没出息的一种概念罢了
网友 7:微前端对一些大型应用开发很有好处的,上百人的开发团队,几十个子系统,每个小组负责两三个子系统即可,团队小的不适用,本质是为了解决存量、巨型应用的维护和迭代问题
网友 8:我们团队从 2017 年开始就是微前端方案,只是一直是基于 iframe 的而已,最近才起项目打算切成单页应用模式,仔细梳理了一下,成本居然不是很高……
网友 9:必须要支持下,此次我们 app 运营系统的改造就运用了这项技术。那可是一套已经拥有 100 多个业务功能的 java web 项目,已经无法与时俱进了,后续可以愉快的使用当下流行的技术栈来开发新的功能
网友 10:你的业务是否真的需要微前端?市面上那么多框架如何选择?汗~
网友 11:很多评论充斥着对微前端的奚落与偏见,没有遇到这种棘手问题是种幸运。 如果纯粹为了用某个技术而刻意使用,就会导致这种不理解与偏见。这往往是因为教程内容并没有很好解释该技术要解决的问题与应用场景(可能写文章的人自己都不知道),从而产生了这种本可以避免的偏见。
从上述网友的观点来看,关于微前端的争议主要集中在以下几个方向:
针对这些争议,我的建议如下:
「1. 考虑业务需求」:在决定是否使用微前端时,应首先考虑业务需求。如果你的项目规模小,或者团队人员少,或者技术栈统一,那么可能并不需要使用微前端。反之,如果你的项目规模大,团队人员多,或者需要使用多种技术栈,那么微前端可能会是一个好的选择。
「2. 权衡成本」:实施微前端架构需要投入一定的时间和人力,你需要权衡这些成本和微前端所能带来的好处。
「3. 选择适合的框架」:在选择微前端框架时,应该考虑框架的成熟度、社区活跃度、文档质量等因素。
「4. 提升团队协作」:微前端架构可以帮助提升团队的协作效率,但这也需要团队成员有一定的技术能力和良好的协作精神。
「5. 关注技术趋势」:作为一种新的架构模式,微前端具有一定的前瞻性,值得我们关注和学习。
总的来说,微前端是一种思维转变,它提出了一种新的前端架构模式,旨在解决大型复杂应用的开发和管理问题。然而,这并不意味着微前端适用于所有的前端项目,也并不意味着微前端是一种银弹。如同任何技术或架构模式,微前端也有其适用的场景和限制。我们应该根据实际的业务需求和团队能力,理性地对待微前端,适时地运用微前端。
微前端架构,作为一种新兴的前端架构模式,对于如何合理评估、精准选择和高效实现提出了新的挑战。接下来,我们将分享一些在实践过程中积累的经验和最佳实践:
总的来说,**微前端架构的实践是一场寻求平衡的旅程**,我们需要在微观与宏观、独立与集成、灵活与稳定之间找到恰当的平衡点。只有这样,我们才能充分发挥微前端架构的优势,同时避免其可能带来的问题。随着前端技术的不断变化和发展,微前端架构也在不断地演化和完善。因此,开发者应关注和学习微前端架构的最新发展,掌握其实现原理和最佳实践,以应对日益复杂的 Web 应用需求,提高项目的可维护性和开发效率。
[1]
single-spa:https://zh-hans.single-spa.js.org/
[2]
qiankun:https://qiankun.umijs.org/zh/guide
[3]
icestark:https://github.com/ice-lab/icestark
[4]
micro-app:https://micro-zoe.github.io/micro-app/docs.html#/
[5]
wujie:about:blank
[6]
12.6k:https://github.com/single-spa/single-spa/stargazers
[7]
14.8k:https://github.com/umijs/qiankun/stargazers
[8]
1.9k:https://github.com/ice-lab/icestark/stargazers
[9]
4.5k:https://github.com/micro-zoe/micro-app/stargazers
[10]
3.2k:https://github.com/Tencent/wujie/stargazers
[11]
链接
:https://juejin.cn/post/6844904202389438478#heading-30
[12]
链接
:https://juejin.cn/post/6844904194818703374
[13]
链接
:https://developer.aliyun.com/article/742576
[14]
链接
:https://tech.meituan.com/2020/02/27/meituan-waimai-micro-frontends-practice.html
作者:车青青
来源:微信公众号:大转转FE
出处
:https://mp.weixin.qq.com/s/48Jy1CXQNzRLUAYDzA0Xbg