FrontJs
FrontJs
Fronts 是一个基于 Webpack 的 Module Federation API 设计的渐进式微前端框架。它强调颗粒间的去中心化依赖管理,并支持多种运行模式来满足不同的微前端架构需求。
特性
-
支持非 Module Federation - 虽然 Fronts 基于 Module Federation 概念, 但它依然支持任何传统且不支持 Module Federation 的前端应用。
-
去中心化配置 - 只需要在每个 Fronts 应用中设置 site.json,就像设置一个 package.json 一样简单,Fronts 支持多层嵌套的微前端。
-
跨框架 - 没有任何现代前端框架限定。
-
代码分割/懒加载 - 支持在 Fronts 应用内进行代码拆分和导出共享模块,它可以被其他 Fronts 应用作为依赖模块进行懒加载。
-
CSS 隔离 - 可选的 CSS 隔离设定,并根据不同的渲染方式有宽松隔离和严格隔离的可选项。
-
生命周期 - 每个 Fronts 应用的 Entry 支持简洁的生命周期接口。
-
Web Components 和 iFrame - 支持多种前端运行时容器用于不同隔离环境要求。
-
多种构建模式 - 同时支持在微前端模式和非微前端模式构建,兼容动态化的运行时集成和静态化的构建时集成。
-
Monorepo 和 TypeScript - 良好支持 Monorepo 和 TypeScript,它们和 Fronts 是非常适合架构在一起的技术栈。
-
版本控制 - Fronts 提供的版本控制可用于高效和动态的即时交付应用,当然也包括支持灰度发布。
-
零劫持 - Fronts 不做任何执行容器上的环境全局公共 API 劫持, 保持运行环境的原始性,避免可能带来性能损失和安全问题。
-
通用化消息通讯 - Fronts 提供简洁通用的响应式 API, 它支持前端绝大部分原生 API。
背景
在众多微前端解决方案中,single-spa 和 Module Federation 是其中的佼佼者。
single-spa 是一个基于以路由配置为主要特点的微前端框架,由微前端配置的中心化带来了一系列限制,诸如较难以颗粒化可嵌套的微前端、弱化模块颗粒度可控、模块共享等,而它以及众多基于它研发的微前端解决方案或多或少都难以摆脱以路由为中心的限制。
2019 年,Zack Jackson提出并实现Module Federation,它的概念与single-spa 完全不同,Module Federation在构建时处理共享模块,它允许在前端应用程序运行时从另一个应用程序资源动态加载代码并共享依赖。Module Federation彻底解决了代码依赖共享问题与微前端运行时模块化问题。这一构想确实也如 Zack Jackson文章提到的它是"A game-changer in JavaScript architecture"。Module Federation 让前端运行时第一次有了和 Node.js 的模块系统有类似设计的可能。Module Federation目前已经被 Webpack,next.js 和rollup所支持。
尽管Module Federation概念如此惊艳,但是它毕竟尚未进一步形成一个完整并完全针对微前端的框架设计与实现,而这就是 Fronts 框架所要做的,并尝试解决一些目前微前端领域中一些热点争议问题。
微前端框架的争议点
基于目前主流的微前端框架或概念,以下整理了主要涉及的争论点:
颗粒级别划分应该是应用级别还是模块级别
从灵活性和颗粒度来说,模块级别显然更具有优势,但是为了兼容一些并不是那么现代的前端工程,支持应用级别显然也有一定的优势,因此我们需要一个两者都能支持框架。如果需要应用级别的运行时集成,显然仅仅只是使用 Module Federation 的 Webpack 是不够的,我们还需要一个运行时的应用级别颗粒入口点加载器。
入口点是 HTML 文件还是 JS 文件为主
从现代工程角度而言,前端应用入口点大多以 JS 为主,而早中期的一些前端工程也不乏仅以 HTML 为入口点,这里有利弊权衡,HTML 为主要入口点的应用来说,建构一个微前端体系,那它必然是一个异步请求(甚至是跨域请求),并能解析其 DOM 结构,再进行一些主动的拆解整理与渲染运行,甚至加入运行时 Sandbox,但这一整体处理流程稍显冗长与繁复,这种拆解库更适合是一个独立的非核心工具包,而整体的框架应该以 JS 文件为入口点。
除了支持入口点,是否有必要支持其非入口点的模块共享
模块共享是微前端的必解之题,否则运行时臃肿与重复的各种资源浪费,将让微前端的落地意义大打折扣。但在早中期的前端模块中,共享依赖主要通过 script 的 HTML 标签来相对静态方式管理模块,而目前也只有 Module Federation 的 Webpack 则让这样的模块共享分离在构建时处理完成,并能进行运行时动态依赖共享。除了 Module Federation,目前还尚未出现其他更完美的解决方案。
CSS/JS 隔离解决方案成本利弊选择
CSS 的隔离是在所难免,这也被不少微前端框架所支持。而 JS 隔离实现成本相对就高了不少,需要异步请求到这个 JS 文件(甚至是跨域),并针对各种可能的访问的全局接口进行全面的劫持代理,既要保证安全性、性能和稳定性,还要考虑不同浏览器的兼容性等方面,其实往往得不偿失,尤其是现代前端工程中甚少全局污染,事实上这样的隔离是否是非常必要,也取决于落地在每个微前端颗粒中的实际情况。如果是外部不可控风险的颗粒,我们往往可以少量地使用 iFrame 来做到真正的 sandbox 隔离,通过约定接口的方式进行交互。而在大多数可控的微前端颗粒中,事实上我们仅仅需要非隔离方式进行在同一个 JS 运行容器上直接地相互访问,这是高效便捷的。
微前端颗粒的通用性,以及是否需要支持多运行容器与多模式,SSR等
在大型前端工程中,往往不会只是以构建一个 Web 应用这样的形式存在,而可能是构建多个 Web 应用,甚至是更多中前端应用类型,例如 Electron 应用、浏览器插件、小程序或移动端应用等。因此一个好的微前端框架应该能够兼容更多种运行容器和打包成多种应用类型,也最好能兼容构建单体应用和微前端应用。Module Federation 也初步实现了在 next.js 实现 SSR 的支持。
版本控制和依赖管理
在大型的成熟前端应用中,不断的快速迭代和业务膨胀,因此各种大小粒度的模块管理变得非常重要,因此当一个大型前端工程试图开始引入微前端架构后,往往演化到后期,版本控制和依赖管理将变得尤为重要,它将很大程度上提升了大型前端工程的交付管理和可维护性。