十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Fiori Elements 项目中 ui5.yaml 的全面解析:本地开发与构建打包的核心配置

Fiori Elements 项目中 ui5.yaml 的全面解析:本地开发与构建打包的核心配置 先从一个非常常见的场景说起一个新同事刚用SAP Fiori tools生成完Fiori Elements项目打开根目录看到一堆配置文件其中就有 ui5.yaml。他问我“这个文件是干嘛的跟 manifest.json 有什么区别我什么时候需要动它” 这个问题其实问到了点子上——很多人能在本地把应用跑起来但一旦要改后端地址、加注解文件、或者把应用打包部署就开始在 ui5.yaml 里乱试试错了也不知道为什么。ui5.yaml 是 UI5 Tooling 的入口配置文件。Fiori Elements 项目的本地启动、请求代理、注解加载、构建打包全都由这个文件控制。这么说吧manifest.json 管的是应用运行时“长什么样、调哪些服务”ui5.yaml 管的是开发期和构建期“这个项目怎么被编译、怎么连后端、怎么起本地服务”。两件事经常被混淆但责任边界非常清晰。这篇文章我会拿一份真实项目里常见的 ui5.yaml 来做逐行拆解同时把那些文档里不会写、但实际开发一定会遇到的坑一起讲掉。无论你是刚开始碰 Fiori Elements还是已经被构建配置折磨过几次这篇文章应该都能帮你少走不少弯路。1. 这个文件到底管什么先分清开发态与构建态1.1 Fiori Elements 项目文件夹里ui5.yaml 站在什么位置先看一个典型的 Fiori Elements 项目根目录长什么样myapp/ ├── webapp/ │ ├── annotations/ // 有时注解文件在这里 │ ├── localService/ // 本地 mock 数据或 metadata.xml │ ├── component.js │ ├── manifest.json │ └── ... ├── annotate/ │ └── annotation.xml // Fiori tools 生成的注解文件也可能在这里 ├── package.json ├── ui5.yaml ├── xs-app.json └── .gitignorewebapp 目录是应用的核心最终部署到服务器上的也是这个目录里的内容。但 ui5.yaml 不在 webapp 里面它在项目根目录。原因很简单它不属于“应用代码”而是属于“构建工具链”。UI5 Tooling 在执行ui5 serve或ui5 build命令时会从当前目录寻找 ui5.yaml读取里面的配置来决定用什么规范解析项目、项目类型是什么、构建时执行哪些自定义任务、本地服务启动时挂哪些中间件。可以把它理解为整个项目的“工地总指挥”而 manifest.json 更像“楼内设计图”。很多人有一个误解以为改了 ui5.yaml 里的内容部署到服务器上就能生效。这里要提前说清楚ui5.yaml 里有一部分配置比如 server 段只在本地开发服务器上生效构建发布后根本不参与运行。如果分不清这一点后面很容易踩坑。1.2 它由谁生成为什么不同项目长得不一样ui5.yaml 通常不是你手写的而是由 SAP Fiori tools 的 Yeoman 生成器自动生成的。不同时期、不同版本的生成器生成的 ui5.yaml 差别非常大。我在项目里见过至少三种形态比较老的项目2020 年前后specVersion 是 0.1metadata 下面有 name 也有 namespace没有 framework 块server 段里通常只有 fiori-tools-proxy 和 fiori-tools-appreload。中间版本specVersion 2.0metadata 只保留 name新增了 builder.customTasks比如 ui5-tooling-transpile-task。新版本specVersion 2.6 或者更高可能带 framework 块builder 里还有 ui5-task-zipperserver 段会多出 fiori-tools-annotation。所以你在网上搜索 ui5.yaml 的配置说明会发现不同文章写的字段对不上这很正常。关键是搞清楚每个字段负责什么而不是死记某个模板。2. 文件头三段specVersion、metadata、type 逐行说清楚先看一份完整的 ui5.yaml 文件头specVersion: 2.0 metadata: name: com.demo.purchaseorder type: application这三段是每个 ui5.yaml 都必须有的骨架。2.1 specVersion配置协议版本不等于 UI5 版本specVersion: 2.0这里的版本号非常容易让人误会。它指的是 UI5 Tooling 读取这个 YAML 文件时所遵循的“配置格式规范版本”跟应用的 SAPUI5 运行时版本比如 1.108.0没有半点关系。可以用一个生活化的类比理解specVersion 像两个人约定用第几版合同模板来签合同。模板换了合同的条款结构可能不同但签合同这件事本身不变。UI5 Tooling 升级后对 ui5.yaml 的解析规则会调整于是需要引入 specVersion 来告诉工具“按哪一版规则读我”。实际开发中要注意的版本对应关系大致如下specVersionUI5 Tooling 时代特点0.1早期版本metadata 需要 name namespace配置比较宽松1.0 / 1.1UI5 CLI 1.x 后期逐渐规范化加入 type 枚举2.0UI5 Tooling 2.xmetadata.namespace 可以省略builder/server 结构定型2.6较新版本与新版 SAP Fiori tools 生成器配套3.xUI5 Tooling 3.x新工具链默认选项大多数情况下你不需要主动改这个值。但如果你把项目从老版本迁移到新工具链比如升级ui5/cli通常需要把 specVersion 一起升上去否则工具会提示配置版本不兼容。2.2 metadata.name 与 namespace应用标识要对齐 manifest.jsonmetadata.name是项目的唯一标识一般格式是“命名空间.应用名”。比如com.demo.purchaseorder表示命名空间是com.demo应用名是purchaseorder。这个 name 必须和webapp/manifest.json里的sap.app/id保持一致。如果两边对不上本地开发可能没太大感觉但构建或者部署到 ABAP 环境时系统按应用 ID 找资源就会出现应用加载不出来或找不到 Component 的问题。在老版本格式里metadata 下面还会单独写一个 namespacemetadata: name: com.demo.purchaseorder namespace: com.demo这是为了让工具知道项目的命名空间和名称分别是多少。到了 specVersion 2.0工具可以从 name 里自动推断命名空间所以 namespace 字段就省略了。如果你在旧项目里看到 namespace不用觉得奇怪它在当时是必须的。2.3 type: application一个值决定构建产物type: application声明这个项目是“应用”而不是“库”或“主题”。对 UI5 Tooling 来说application 和 library 的构建流程差异很大。application 类型构建时工具会做这些事把 webapp 下的资源复制到 dist 目录生成 Component-preload.js处理 i18n 文件的合并与压缩生成 cachebuster 信息。最终产物是一个可以独立部署的应用包。如果误配成 library构建出来的目录结构和资源加载方式都会变最常见的结果是应用页面白屏因为 Component.js 的加载路径不对。对于 Fiori Elements 项目来说type 永远应该是 application因为 Fiori Elements 本身就是一个 SAPUI5 应用只是页面框架由后端注解驱动生成。3. resources 和 builder构建阶段 Fiori Elements 项目会经历什么文件头的三段看完接着是 resources 和 builder 段。这一块管的是“构建时对这个项目做什么加工”。resources: configuration: propertiesFileSourceEncoding: UTF-8 builder: customTasks: - name: ui5-tooling-transpile-task afterTask: replaceVersion configuration: debug: true removeConsoleLog: true transformAsyncToPromise: true - name: ui5-task-zipper afterTask: generateCachebusterInfo configuration: archiveName: purchaseorder additionalFiles: - xs-app.json3.1 propertiesFileSourceEncoding中文乱码的隐藏开关resources.configuration.propertiesFileSourceEncoding指定项目里*.properties文件的编码方式。这个配置太容易被人忽略但它直接决定了 i18n 文件里的中文会不会乱码。SAPUI5 的属性文件默认按 ISO-8859-1 处理。如果你在i18n.properties里直接写中文而且没有声明 UTF-8 编码构建后这些中文会变成乱码界面上满屏的问号。把它设置为UTF-8等于明确告诉构建工具请用 UTF-8 读取这些属性文件。这是一个“没有报错但界面全乱”的典型问题排查起来也很隐蔽我建议项目一创建就先确认这一行在不在。3.2 builder.customTaskstranspile 和 zipper 各干什么customTasks 是在标准构建流程中插入的自定义任务。Fiori Elements 项目里最常见的两个是ui5-tooling-transpile-task和ui5-task-zipper。ui5-tooling-transpile-task负责把现代 JavaScript 或 TypeScript 转译成更兼容的版本。新版 Fiori elements 模板默认支持 TypeScript所以构建时需要一个转译步骤把 TS 转成 JS顺便可以去掉 console.log。afterTask: replaceVersion表示这个任务要排在标准任务 replaceVersion 之后执行。UI5 Tooling 的构建流程是一串有序任务clean、copy、replaceVersion、generateCachebusterInfo 等。自定义任务通过 afterTask 或 beforeTask 声明自己挂在哪个标准任务前后。这个机制很像 Express 中间件核心就是“控制顺序”。ui5-task-zipper更直白构建完成后把 dist 目录打成一个 zip 包。archiveName是 zip 包的名称additionalFiles可以额外把项目根目录下的文件比如xs-app.json也塞进 zip 里。xs-app.json是 SAP BTP 环境里应用路由器App Router的配置。你要把 Fiori Elements 应用部署到 BTP Cloud Foundry 环境时这个文件和应用包必须在同一个归档里所以生成器会自动把它加进 additionalFiles。3.3 framework 块新版本生成器带来的依赖清单新版 SAP Fiori tools 生成器还可能在 ui5.yaml 里生成一个 framework 块framework: name: SAPUI5 version: 1.120.0 libraries: - name: sap.m - name: sap.ui.core - name: sap.ushell - name: themelib_sap_fiori_3它的作用是声明这个应用依赖哪个版本的 SAPUI5 框架以及依赖哪些 UI5 库。UI5 Tooling 在构建时会根据这个清单从配置的资源服务器下载对应版本的框架资源到本地。注意 framework.version 是“运行时框架版本”它不是随便填的。Fiori Elements 对不同 SAPUI5 版本的支持范围有严格要求版本选得太低很多控件行为不一致版本选得太高又可能与后端 S/4HANA 系统版本不匹配。一般生成器会根据你在创建项目时选的版本自动填不建议手动乱改。老版本项目没有 framework 块它们的运行时资源来源在 server 段的 fiori-tools-proxy 配置里指定这就是下一章的内容。4. server 域本地开发时的代理、注解映射和自动刷新server 段是本地的开发服务器配置也是 Fiori Elements 项目里最值得逐行研究的区域。先看完整配置server: customMiddleware: - name: fiori-tools-proxy afterMiddleware: compression configuration: ignoreCertError: false backend: - path: /sap url: http://vhcalserver.example.com:8000 client: 100 ui5: path: - /resources - /test-resources url: https://ui5.sap.com version: 1.108.0 - name: fiori-tools-appreload afterMiddleware: compression configuration: port: 35729 path: webapp - name: fiori-tools-annotation beforeMiddleware: fiori-tools-appreload afterMiddleware: fiori-tools-proxy configuration: annotations: - localPath: annotate/annotation.xml urlPath: /annotate/annotation.xml4.1 fiori-tools-proxy请求是怎么翻到后端 OData 服务上的fiori-tools-proxy 是 SAP Fiori tools 提供的核心代理中间件。本地开发时Fiori Elements 应用运行在http://localhost:8080但 OData 服务在真正的后端 ABAP 系统上比如http://vhcalserver.example.com:8000。浏览器直接请求后端会有跨域问题而且后端的地址也不应该写死在应用代码里所以中间件就在中间做了一层转发。afterMiddleware: compression表示这个代理中间件插在压缩中间件后面。compression 是 UI5 服务器内置的 gzip 压缩组件先压缩再代理性能更好。configuration 里的 backend 数组是关键backend: - path: /sap url: http://vhcalserver.example.com:8000 client: 100这条规则的语义是凡是本地请求路径以/sap开头的全部转发到http://vhcalserver.example.com:8000。path的匹配粒度直接影响调试体验。Fiori Elements 应用默认的 OData 服务路径通常是/sap/opu/odata/sap/...如果你只配了/sap/opu/odata那还好但有些应用还会请求/sap/bc/ui2/...这类系统资源如果 path 覆盖不到那些请求就会 404。所以大多数情况下直接配/sap是最省心的做法。如果项目同时连多个后端服务可以配置多个 backend 条目每个条目指定不同的 path 前缀。client: 100是 SAP 系统客户端号。连后端系统时如果不指定默认用系统默认客户端很多测试环境实际数据在特定客户端里这个值不对登录进去可能什么都查不到。配置里还可能看到destination字段。这个字段在部署到 SAP BTP 时用来关联 Cloud Connector 里的目的地。本地开发时如果你连的是远程系统destination 一般不是必需的真正决定转发目标的是 url。ignoreCertError: false控制是否忽略自签名证书错误。本地用 http 连接时无所谓如果后端是 https 且证书不受信任这里要临时改成 true 才能连通。这个字段在实际联调测试系统时很常用我经常为了连一个测试环境把它改成 true调完再改回来。再看 ui5 子配置ui5: path: - /resources - /test-resources url: https://ui5.sap.com version: 1.108.0这个配置解决的是本地开发时 UI5 框架资源从哪里加载的问题。Fiori Elements 应用运行时会请求/resources和/test-resources这两个路径下的框架资源代理中间件看到这些请求后不是转发给 ABAP 后端而是从https://ui5.sap.com上拉取指定版本的 UI5 资源返回给浏览器。这算是“动态 CDN”思路本地不用安装完整的 SAPUI5 框架启动服务时按需从 CDN 拉。但要注意公司内网环境往往访问不了外网这种情况下本地启动会一直卡在加载框架资源的环节。解决办法是把 url 换成公司内部的 UI5 资源镜像地址或者干脆把 ui5 配置去掉改用本地 node_modules 里的 OpenUI5 资源。4.2 fiori-tools-annotation本地注解文件如何变成可访问 URLFiori Elements 和普通 SAPUI5 应用最大的区别就是“页面由注解驱动”。注解文件annotation.xml定义了列表页有哪些字段、哪些按钮、哪些跳转关系。没有注解Fiori Elements 应用就只是一张白纸。本地开发时注解文件通常还没发布到后端它就躺在项目文件夹里。fiori-tools-annotation 中间件的作用就是把这个本地文件“伪装”成一个 URL 端点让应用运行时能访问到。annotations: - localPath: annotate/annotation.xml urlPath: /annotate/annotation.xmllocalPath 是本地文件路径urlPath 是暴露出来的访问路径。配置好之后你在浏览器里直接访问http://localhost:8080/annotate/annotation.xml就能看到这个文件的内容。然后应用通过manifest.json里的 dataSources 配置引用这个 URLdataSources: { mainDataSource: { uri: /sap/opu/odata/sap/ZSERVICE_SRV, type: OData }, annotation: { uri: /annotate/annotation.xml, type: ODataAnnotation } }这里有个很容易混淆点/annotate/annotation.xml并不是真实存在于 webapp 目录下的文件它是中间件“造”出来的。本地启动服务后这个 URL 才有效这也是为什么很多人在部署到服务器后发现注解突然全部失效——因为服务器环境没有跑 fiori-tools-annotation 这个中间件。4.3 fiori-tools-appreload 与中间件顺序fiori-tools-appreload 是热重载livereload中间件- name: fiori-tools-appreload afterMiddleware: compression configuration: port: 35729 path: webapp它监听 webapp 目录下的文件变化一旦有改动就通过 35729 端口通知浏览器刷新页面。port 是 livereload 的通信端口path 是监听目录。这个配置看着简单但中间件的顺序值得多说一句。UI5 Tooling 的中间件执行顺序不是简单按 YAML 列表顺序来的而是通过 afterMiddleware 和 beforeMiddleware 这两个字段声明。比如前面示例里fiori-tools-annotation 写了beforeMiddleware: fiori-tools-appreload afterMiddleware: fiori-tools-proxy意思是annotation 中间件要排在 fiori-tools-proxy 之后、fiori-tools-appreload 之前。这样请求到达应用时先经过代理转发 OData再映射注解文件最后注入自动刷新脚本。实际开发中我一般不会手动调整这三个中间件的顺序生成器生成的默认顺序基本是合理的。知道这个机制的目的在于如果你在 ui5.yaml 里新增了一个自定义中间件结果发现它没有生效或者把应用搞挂了第一反应应该是检查它挂载的位置顺序而不是怀疑代码本身写错了。4.4 把示例文件完整过一遍为了更直观我把前面拆过的所有内容拼成一份完整配置从头到尾标上作用specVersion: 2.0 # 配置协议版本告诉UI5 Tooling按2.0规范解析本文件 metadata: name: com.demo.purchaseorder # 项目唯一标识与manifest.json的sap.app/id一致 type: application # 项目类型application会走应用构建流程 resources: configuration: propertiesFileSourceEncoding: UTF-8 # i18n属性文件按UTF-8读取避免中文乱码 builder: customTasks: - name: ui5-tooling-transpile-task # TypeScript/ES6转译任务 afterTask: replaceVersion # 在replaceVersion标准任务之后执行 configuration: debug: true # 转译时保留调试信息 removeConsoleLog: true # 转译时移除console.log transformAsyncToPromise: true # async/await转成Promise链写法 - name: ui5-task-zipper # 打包任务 afterTask: generateCachebusterInfo # 在生成缓存信息之后执行 configuration: archiveName: purchaseorder # 最终zip包名称 additionalFiles: - xs-app.json # 把应用路由配置一并打入zip包 server: customMiddleware: - name: fiori-tools-proxy # 请求代理中间件 afterMiddleware: compression # 在gzip压缩之后执行 configuration: ignoreCertError: false # 不忽略自签名证书错误 backend: - path: /sap # 匹配以/sap开头的请求 url: http://vhcalserver.example.com:8000 # 转发到ABAP后端地址 client: 100 # 后端系统客户端号 ui5: path: - /resources # UI5框架资源请求路径 - /test-resources # 测试框架资源请求路径 url: https://ui5.sap.com # 从SAP官方CDN拉取资源 version: 1.108.0 # SAPUI5框架版本 - name: fiori-tools-appreload # 热重载中间件 afterMiddleware: compression # 在gzip压缩之后执行 configuration: port: 35729 # livereload通信端口 path: webapp # 监听webapp目录变化 - name: fiori-tools-annotation # 注解文件映射中间件 beforeMiddleware: fiori-tools-appreload # 在热重载之前 afterMiddleware: fiori-tools-proxy # 在代理之后 configuration: annotations: - localPath: annotate/annotation.xml # 本地注解文件位置 urlPath: /annotate/annotation.xml # 对外暴露的URL路径这样一份配置本地开发时能跑通构建时也能正常出包。但现实世界里项目不可能永远停留在这个理想状态。5. 不同生成器版本对比和几个高频问题5.1 新老 Fiori tools 生成的项目ui5.yaml 差在哪由于生成器的迭代很快你手上这个项目的 ui5.yaml 跟我上面示例可能不完全一样。我整理过一份新老配置对照方便你判断自己项目属于哪种配置项老项目新项目specVersion0.12.0 或更高metadata.namespace单独声明省略从 name 推断framework 块无有声明框架版本与依赖库ui5-tooling-transpile-task无有TypeScript 模板标配ui5-task-zipper无有部署 BTP 时打包用fiori-tools-annotation有时有部分项目已改为 webapp/annotations 方式fiori-tools-proxy 的 ui5 配置常见部分项目不再需要最后一行尤其值得注意。新项目如果配置了 framework 块本地运行时框架资源也可以通过 UI5 Tooling 的框架解析机制从本地或配置的资源库获取fiori-tools-proxy 里的 ui5 部分就不是必需的了。老项目则是完全靠代理中间件从 CDN 拉资源。如果你要升级一个老项目的 ui5.yaml建议按这个顺序来先备份原文件再用新版生成器新建一个同类型项目对照差异最后逐一迁移。不要直接抄一份新模板过来覆盖因为老项目的 webapp 目录结构和依赖未必支持新的构建任务。5.2 按需求找位置改后端、加注解、换 UI5 版本开发中经常遇到的需求对应到 ui5.yaml 的修改位置可以记成一张速查表需求修改位置注意事项本地连接另一个后端系统fiori-tools-proxy.backend 里的 url、client确认 path 前缀覆盖要访问的服务路径本地不再需要代理某路径删除或注释 backend 条目应用请求该路径时回落到本地资源增加注解文件fiori-tools-annotation.annotations 数组里加一项同时在 manifest.json 的 dataSources 里注册切换 SAPUI5 版本framework.version 或 fiori-tools-proxy.ui5.version确认 Fiori Elements 支持该版本公司内网访问不了外网把 ui5.url 换成内网镜像或配置 framework 走本地否则启动后框架资源一直加载失败构建产物要带 xs-app.jsonui5-task-zipper 的 additionalFiles部署 BTP 时必需这张表我建议保存下来。大多数“本地起不来”“部署后不对”的问题都能在这里找到对应的修改入口。5.3 我踩过的三个坑与排查思路第一个坑是注解文件在部署后全部丢失。项目用的还是老结构annotation.xml 放在项目根目录的 annotate 文件夹下靠 fiori-tools-annotation 中间件映射成 URL。本地一切正常列表页字段、按钮都在。但把应用构建后部署到 BTP登录进去页面只剩基础框架完全看不到注解驱动的界面。排查链路是这样的先在浏览器 F12 看 Network发现请求/annotate/annotation.xml返回 404再看构建产物 dist 目录里面根本没有 annotate 文件夹最后才反应过来fiori-tools-annotation 是开发服务器中间件构建时不会把项目根目录下的 annotate 复制到 dist。解决方法是把 annotation.xml 挪到webapp/annotations/annotation.xml并把 manifest.json 里的 dataSources 指向相对路径比如annotations/annotation.xml。这样注解文件作为应用资源的一部分参与构建部署后依然可访问。第二个坑是 OData 请求 404但页面能正常加载。现象是应用能起来列表出不来控制台一堆 404。打开 Network 看到请求 URL 是/sap/bc/ui2/...开头的而我 ui5.yaml 里 backend.path 只配了/sap/opu/odata。path 匹配不上请求就没被代理自然 404。后来我把 path 改成/sap问题立刻消失。这个教训是除非你有特殊的多后端路由需求path 最好配宽一点。遇到 404 先看路径前缀再看后端地址能不能通不要一上来就怀疑代理中间件本身。第三个坑不那么起眼但很耽误时间TypeScript 项目构建失败报错找不到ui5-tooling-transpile-task模块。原因是 package.json 的 devDependencies 里没有安装这个任务包或者版本跟本地的ui5/cli不兼容。生成器生成的模板默认会把这些依赖写进 package.json但你如果手动清理过依赖很容易把它们误删。遇到这种构建报错我的排查顺序是先看服务端日志里缺失的模块名再到 package.json 确认依赖是否存在最后npm install对应模块并检查版本。这类问题大多是环境依赖问题不是配置语法问题。写在最后ui5.yaml 对我来说更像是项目的“开发环境说明书”。它不是每天都要改但每次改动都影响开发效率和最终产物。理解它之后你再遇到本地连不上后端、注解加载失败、构建产物缺文件这类问题第一反应一定是去对应的配置段找原因而不是靠猜。最后分享一个小建议每次改 ui5.yaml 之前先复制一份备份命名成ui5.yaml.bak。这个文件不像代码有 git 分支那么直观改动出错后想恢复手边没有备份就只能重新生成项目对比差异了。别问我怎么知道这有多麻烦。
返回列表