本地修改远端 SAP UI5 框架文件的一个小技巧
这是 Jerry 2021 年的第 64 篇文章,也是汪子熙公众号总共第 341 篇原创文章。
八阵图
杜甫
功盖三分国,
名成八阵图。
江流石不转,
遗恨失吞吴。
Jerry 的前一篇文章 纪念特洛伊英雄 Sinon - SAP UI5 Mock Server 使用步骤和工作原理介绍,提到了 SAP UI5 Mock Server,能够在幕后将浏览器原生的 XMLHttpRequest API,替换成基于 Sinon.js 实现的 FakeXMLHttpRequest,从而实现为所有 OData 相关的请求,返回事先准备好的 Mock 数据之目的。
文末提到了拦截器 HTTP Interceptor 的概念。在 HTTP 拦截器的工作场景中,HTTP 请求在两个时间点内,可以被框架或者应用开发人员编写的拦截器处理:
程序代码调用 API 发送 HTTP 请求后,在 HTTP 请求实际从浏览器发出之前,由拦截器进行预处理
应用程序得到远端的服务器响应后,在交给其回调函数处理之前,由拦截器进行预处理
本文介绍一个使用拦截器的实际例子。
我们知道 SAP UI5 打开调试模式后,在 Console 控制台会看到很多额外的来自 SAP UI5 框架代码的 log 输出。
Jerry 曾经在 SAP 社区上写过一篇博客,罗列出了我在 SAP CRM Fiori 开发团队工作时,通过单步调试的方式解决的一些 bug:
My UI5 debugging tips and experience collection – how to resolve UI5 issues through debugging by yourself
https://blogs.sap.com/2016/04/30/my-ui5-debugging-tips-and-experience-collection-how-to-resolve-ui5-issues-through-debugging-by-yourself/
文章里提到的不少例子里,我都在 SAP UI5 框架代码里加上了一些额外的 console.log, 然后观察其运行时打印出的内容。这种方法能帮助我在排除错误和学习 SAP UI5 框架实现原理时,更好地了解其执行细节。
比如文章 深入学习SAP UI5框架代码系列之八:谈谈 SAP UI5 的视图控件 ID,以及其和 Angular 视图的异同 里介绍了 SAP UI5 控件 ID 的生成逻辑:
如果开发人员显式指定了控件 ID,则使用该 ID 生成 HTML 原生标签
如果开发人员没有指定控件 ID,则使用控件元数据里包含的前缀,加上全局计数器自动生成 ID
假设我们想直接在 Chrome 开发者工具 Sources 面板里如上图所示的 SAP UI5 框架文件 ManagedObject-dbg.js 里,添加一行 console.log 语句打印出控件 ID:
保存之后,我们会看到该文件左边有一个小的黄色惊叹号图标,以及一行警告消息:
Changes to this file were not saved to file system.
一旦刷新浏览器,之前对 ManagedObject-dbg.js 的修改就丢失了。
原来,Chrome 开发者工具的 Sources 面板,提供了一个简易的 Workspace(工作区)功能。
我们可以点击上图的加号按钮,将某个本地文件夹添加到 Chrome 开发者工具的工作区中去。
接下来,在该本地文件夹内启动 Web 应用,就能在 Chrome 开发者工具 Sources 标签内,看到加载的文件。更妙的是,此时我们直接在 Chrome 开发者工具里编辑加载的文件,修改会自动同步到本地文件中去。
例如,我把名为 walkthrough 的本地文件夹添加到 Chrome 开发者工具的工作区内:
接下来,我在 Chrome 开发者工具里直接编辑该文件夹下的 index.html, 保存。然后重新刷新浏览器,发现之前的修改已经被持久化到本地的 index.html 文件里去了,同时在 Chrome 开发者工具里被修改的文件左边,有一个绿色的圆点作为提示。
在回到之前试图修改的 SAP UI5 框架文件 ManagedObject-dbg.js. 因为我是通过远端加载的方式,从 openui5.hana.ondemand.com 服务器导入 SAP UI5 库文件,因此本地并未存储 SAP UI5 框架文件,所以无法使用 Chrome 开发者工具的工作区映射功能。
此时 HTTP 拦截器就派上用场了。使用拦截器,将浏览器加载 ManagedObject-dbg.js 的请求拦截下来,返回另一个我们事先准备好的加上了 console.log 语句的 JS 文件即可。
这里我使用的拦截器软件是 Fiddle,一个网络抓包工具,可以将网络传输发送与接受的数据包执行截获,编辑,转存,重发等操作。用来实现本文描述的文件请求拦截场景,更是杀鸡用牛刀,小菜一碟。
打开 Fiddle,在监控的网络请求里,找到并选中对 ManagedObject-dbg.js 的请求,打开右侧的 AutoResponder 面板:
勾上 "Enable rules" 之前的 checkbox,维护一条规则,其语义为:如果 Fiddle 检测到一条请求的 url 为规则指定的值,则返回一个事先准备好的,包含了 console.log 的同名本地文件:
刷新浏览器,如今在 Fiddle 面板里能观察到,当请求文件 ManagedObject-dbg.js 时,返回的响应里,确实包含了我们手动添加的 console.log 语句,说明规则执行成功。
然而在 Console 面板里,发现一条和跨域访问相关的错误消息:
Access to XMLHttpRequest has been blocked by CORS policy: No Access-Control-Allow-Origin header is present on the requested resource.
在 Chrome 开发者工具 Network 标签页里查看该请求的响应头部字段,发现果然缺少 Access-Control-Allow-Origin 字段:
Ctrl + R 打开 Fiddle 的自定义规则编辑器:
使用脚本,将缺失的 Access-Control-Allow-Origin 字段添加到响应头部即可:
之后,我们能在 Chrome 开发者工具里看到期望中的被 Fiddle 自定义规则编辑器所添加到 HTTP 响应的头部字段:
为了让我们自定义的 console.log 显示的内容不至于淹没在海量的 SAP UI5 框架日志里,我们可以利用 console.log 函数的第二个格式参数,让我们的打印输出变得醒目一些:
关于该参数的详细用法,请参考我的博客:
Chrome Development Tool tips used in my daily work
https://blogs.sap.com/2016/03/15/chrome-development-tool-tips-used-in-my-daily-work/
希望本文能帮助大家对 Web 开发利器之一,Fiddle 软件的使用有一个直观的感受,感谢阅读。
Jerry 的 SAP UI5 专题