Uber 的 Web 平台团队开发 Fusion.js,一个开源的 Web 框架,用于简化 Web 开发,并构建出高性能的轻量级 Web 应用程序。
随着 Web 最佳实践的发展,Uber 需要改造已有的单体 Web 框架,解决长达数年的技术债务所带来的挑战。我们还希望让工程师们能够继续使用他们喜欢的技术(例如 React 和 Redux),同时保持与 Uber 健康监控基础设施的兼容性。
具体来说,Uber 希望核心框架能够解决以下痛点:
服务器端渲染、代码拆分和模块热加载所需的复杂配置和工具样板代码
在涉及服务器端渲染的 React 应用程序时,缺乏用于实现和共享特性的良好抽象
不同位置的代码紧密耦合而导致的脆弱性
测试难度攀升
单体框架缺乏灵活性
虽然现有的解决方案解决了其中的一些挑战,但我们发现,基于框架添加新库通常需要修改多个不相关的文件。例如,要让可进行服务器端渲染的应用程序支持 Redux, 通常需要在服务器相关的文件中添加代码,并在客户端添加类似的代码,还要向 HTML 模板中添加 hydration 代码,使用 React Provider 组件等。要集成 i18n 库或添加浏览器性能指标库也是一样。
很多特定于应用程序的代码可能会依赖用于管理副作用的库(例如用于日志记录或数据持久化的库),工程师很难在没有服务层抽象的帮助下以可测试的方式集成这些库。
我们既希望能够为与 Uber 现有库集成提供简单且经过实战考验的解决方案,也希望能够避免使用单体框架,从而保持捆绑包的小体积。
我们倾向于选择模块化方法的另一个原因是,我们必须明确指定依赖关系,这样可以更容易避免技术债务,如 God Object(https://en.wikipedia.org/wiki/God_object)、临时内部接口和紧密耦合。
Fusion.js 是我们努力的结晶。
简单地说,Fusion.js 是一个 MIT 许可的 JavaScript 框架,支持 React 和 Redux 等流行库,并提供了很多现代特性,如模块热加载、数据感知服务器端渲染和捆绑拆分支持。
除了预配置的样板,Fusion.js 还提供了灵活的基于插件的架构。因此它非常适合用于现代单页应用程序以及依赖复杂服务层来满足各种质量要求的现代 Web 应用程序。
有关 Fusion.js 的更多信息,请查看项目文档。
Fusion.js 应用程序是通用的,也就是说它有一个单入口文件,并且可以在服务器和浏览器上重用代码。在通用的应用程序中,React 组件还可以获取数据并在服务器上渲染 HTML,从而可以利用浏览器的原生 HTML 解析器和避免 JavaScript DOM API 的开销来减少页面加载时间。
单入口架构使 Fusion.js 插件本身也具有通用性,插件开发人员可以将代码片段与代码所属的库放在一起,而不是与代码运行的环境放在一起。
Fusion.js 插件基于逻辑分组封装逻辑,而不是基于需要添加代码的位置
插件可以通过中间件访问 HTTP 请求生命周期,也可以访问 React 树,以便添加 Provider 组件。它们还可以初始化浏览器代码。
最后,由于这些特性,我们可以通过单行代码将库安装到应用程序中,无论库需要多少个不同的集成点。由于插件易于添加和删除,因此在重构时也很容易推断它们之间的耦合度、对包大小的影响以及其他代码质量属性。它们也可以初始化浏览器代码。
插件利用了依赖注入,这意味着它们可以将定义良好的 API 作为服务暴露给其他插件,并且在测试期间可以轻松地模拟插件的依赖项。当依赖关系负责与数据存储基础设施打交道或与可观察性(例如日志记录、分析和指标)相关时,这一点尤为重要。
/*
这个例子实现了一个从 session 读取数据的端点。
Session 是通过依赖注入的方式提供的。
SessionToken 是一个标签 (用于确保类型安全)。
*/
// src/plugins/user.js
import {createPlugin} from 'fusion-core';
import {SessionToken} from 'fusion-tokens';
export default __NODE__ && createPlugin({
deps: {Session: SessionToken},
middleware({Session}) {
return async (ctx, next) => {
if (ctx.path === '/api/user') {
ctx.body = JSON.parse(await Session.from(ctx).get('user'));
}
return next();
}
}
});
还可以借助 Flow.js 来确保依赖之间的静态类型安全,如下所示:
直接在代码编辑器中显示错误有助于在代码运行之前捕获错误
几年前就存在这样的一个挑战,流行的 HTTP 服务器库 Express 有一个 API 让复杂的响应转换变得难以封装和测试。在 Uber 以前的架构中,应用程序开发人员经常需要采用临时包含 Express 请求 / 响应对象的特定补丁。自然而然地,因为子系统对时间要求的高度耦合,测试变得极其困难。
在开始设计 Fusion.js 时,我们就一直关注这个问题。经过大量调研,我们决定使用 Koa(https://koajs.com),它提供了基于上下文的 API,对单元测试非常友好,并为请求生命周期管理提供了一个基于下游和上游概念的轻量级抽象。
事实证明,采用 Koa 是一个正确的设计决策。
Koa 中间件为 React Provider 组件提供逻辑集成点,下游 / 上游抽象与 React 服务器渲染上下文的生命周期完美匹配。网络副作用与应用程序逻辑分离,从而提高了可测性。
Fusion.js 的依赖注入和图解析机制解决了困扰我们已久的 God Object 和操作顺序问题。
Fusion.js 核心将网络副作用与应用程序状态隔离开来,并利用 Koa 和 DI 来实现子系统之间的松散耦合
在过去的几年里,JavaScript 生态系统中出现了大量高质量的测试工具,并提高了对测试技术的认识。
除了支持 Jest、Enzyme 和 Puppeteer 等现代测试工具外,Fusion.js 还为开发人员提供了测试插件的工具。fusion-test-utils 包允可用于模拟服务器本身,从而可以在插件和各种桩的组合上快速运行集成测试。
在 Uber 内部,已有 60 多个项目代码库在使用 Fusion.js。我们预计这个数字会继续增加,因为新的 Web 项目也在不断创建,同时旧项目被自动迁移到 Fusion.js。因此,框架级别的改进应该能够显著改善这些项目的软件质量基准。
我们的路线图包括添加更多的性能优化和面向测试的工具,以及更好的 Flow 支持。
介绍内容来自 InfoQ
Uber引入了一个名为Fusion.js的开源Web框架,该框架以插件体系结构为基础。 JavaScript框架旨在开发高性能,轻量级的应用程序,可在服务器和浏览器上提供代码重用,并可与React和Redux等库一起使用。 [在InfoWorld上更深入: 超越jQuery:JavaScript框架专家指南 • Node.js框架的完整指南 • 10个必备JavaScript开发人员工具 • 6个
FusionChart中js参数为中文乱码解决的步骤: 1、统一编码为UTF-8。 (因为我的代码都是UTF-8的,所以在这个地方就统一为UTF-8了,其他的编码方式是否也是这样处理,需要再测试了。) 2、js写法:<set link="javascript%3AgenSonReport%28%26apos;12325%26apos;%29%3B" value="9" /> 它代表的含义是:<
fusion.dll Uber引入了一个名为Fusion.js的开源Web框架,该框架以插件体系结构为基础。 JavaScript框架旨在开发高性能,轻量级的应用程序,可在服务器和浏览器上提供代码重用,并与React和Redux等库一起使用。 [在InfoWorld上更深入: 超越jQuery:JavaScript框架专家指南 • Node.js框架完整指南 • 10个必备JavaScript开发
Uber宣布开源Fusion.js,这是一个“基于插件的通用Web框架”。在发布说明中,Uber的高级软件工程师Leo Horie说到,Uber已经构建了上百个基于Web的应用,随着Web技术的快速变化和最佳实践的持续演化,让数百位Web工程师充分利用现代语言的特性,同时还要跟上Web平台的动态化发展确实是一项很大的挑战。而Fusion.js就是Uber为该问题所给出的解决方案。\\ 在评估框架的
by Dariya Kursova 通过达里娅·库尔索娃(Dariya Kursova) Node.js到底是什么?为什么要使用它? (What exactly is Node.js and why should you use it?) JavaScript as programming language and data format (JSON) has changed web develo
1、问题描述: 使用fusion中的树组件的时候,想默认展开全部或展开自定义的一些树节点时,不能够展开; 2、解决该问题时的测试: 使用异步加载的时候,不能够展开树节点(出问题的代码);使用静态数据的时候,可以展开树节点(测试的代码); 看到这里就很疑惑,为啥异步加载的不行呢,那么找到问题所在了,这个问题是由异步加载引起的,我从网上找了这个解决方案 3、出现问题的代码 <div clas
问题内容: 请提供有关如何为Java Web应用程序执行“插件”体系结构的建议。 当前,我们在Tomcat servlet容器中使用了非常简单和标准的Spring + Hibernate + Struts 2 。(内置Maven) 我需要像Redmine 这样的东西。可以启用/禁用,更新任何模块的位置Redmine UI 请排除OSGi,Portlet等繁重的选项。 OSGi太重,没有很好地采用W
问题内容: 在Node.js中,我可以使用EventEmitter轻松地制作WordPress副本,以将钩子系统复制并构建到CMS核心中,然后可以将其附加到插件中。 对于编写并移植到Go的CMS,我现在需要相同级别的可扩展性和核心隔离。基本上,我现在已经完成了核心工作,但是为了使其真正灵活,我必须能够插入事件(挂钩),并使插件具有附加功能并附加到这些挂钩上。 我不在乎重新编译(动态/静态链接),只
有没有人有过自动化桌面应用程序(不是web)的经验?我需要一个类似于Appium的解决方案来将它与我的移动自动化集成(用Appium、Java编写)。 我们公司在3个平台上都有一个messenger客户端:Android、iOS和桌面。客户端数据在这些平台之间同步。我们已经有了移动平台的基本自动化(使用Appium)。现在我需要为桌面开发自动化。 我想要一个类似Appium的解决方案,这样就可以很
背景 在阅读这个文档前,你应当熟悉Chromium的多进程架构。 概述 插件是浏览器不稳定的主要来源。插件也会在渲染器没有实际运行时,让进程沙箱化。因为进程是第三方编写的,我们无法控制他们对操作系统的访问。解决方案是,让插件在各自独立的进程中运行。 设计细节 进程内插件 Chromium有着在进程内运行插件的能力(对测试来讲非常方便),也可以在进程外运行插件。它们都始于我们的非多进程WebKit嵌
本文向大家介绍基于vue框架手写一个notify插件实现通知功能的方法,包括了基于vue框架手写一个notify插件实现通知功能的方法的使用技巧和注意事项,需要的朋友参考一下 简单编写一个vue插件,当点击时触发notify插件,dom中出现相应内容并且在相应时间之后清除,我们可以在根组件中设定通知内容和延迟消失时间。 1. 基础知识 我们首先初始化一个vue项目,删除不需要的组件和样式,主要针对
pbgo是我们专门针对本节内容设计的较为完整的迷你框架,它基于Protobuf的扩展语法,通过插件自动生成rpc和rest相关代码。在本章第二节我们已经展示过如何定制一个Protobuf代码生成插件,并生成了rpc部分的代码。在本节我们将重点讲述pbgo中和Protobuf扩展语法相关的rest部分的工作原理。 4.7.1 Protobuf扩展语法 目前Protobuf相关的很多开源项目都使用到了
2018年5月24日更新:我们现在有3个版本的Angular从我原来的帖子,仍然没有一个最终可行的解决方案。Lars Meijdam(@LarsMeijdam)提出了一个有趣的方法,当然值得一看。(由于专有问题,他不得不临时删除他最初发布样本的GitHub存储库。但是,如果您想要副本,您可以直接给他发消息。有关更多信息,请参阅下面的评论。) Angular 6最近的架构变化确实让我们更接近解决方案
本文向大家介绍PHP基于PDO调用sqlserver存储过程通用方法【基于Yii框架】,包括了PHP基于PDO调用sqlserver存储过程通用方法【基于Yii框架】的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了PHP基于PDO调用sqlserver存储过程的方法。分享给大家供大家参考,具体如下: 由于业务这边存储过程一直在sqlserver上面,所以要用php去调用它,然而我们本地的是