项目背景
在鸿蒙的 H5 混合开发里,Web 组件一旦加载本地页面,内部的网络请求就可能碰到跨域限制。后台如果没配好,这类问题在前端侧会直接炸出来,表现就是资源访问失败。
问题本身
Web 组件本质上还是浏览器内核,浏览器有的跨域限制它也有。官方文档里给了客户端侧的处理方式:解决 Web 组件本地资源跨域问题 - 管理 Web 组件的网络安全与隐私-ArkWeb(方舟 Web)-应用框架 - 华为 HarmonyOS 开发者
为什么会拦截
为了提高安全性,ArkWeb 内核不允许 file 协议或者 resource 协议访问 URL 上下文中来自跨域的请求。因此,在使用 Web 组件加载本地离线资源的时候,Web 组件会拦截 file 协议和 resource 协议的跨域访问。可以通过设置路径列表,再使用 file 协议访问该路径列表中的资源,允许跨域访问本地文件。当 Web 组件无法访问本地跨域资源时,开发者可以在 DevTools 控制台中看到类似以下报错信息。
这段话的意思很直接:你用本地协议加载页面,ArkWeb 就会更严格一些,不会像普通线上页面那样放得很开。
官方给的两种路子
官方文档里其实就两种思路。
第一种是把本地资源换成 http 或 https 协议来加载,再通过 Web 组件的 onInterceptRequest 去拦截和映射本地资源。这个方案更通用,但改动会大一点,适合你本来就愿意把资源访问链路重新整理一遍的场景。
第二种是通过 setPathAllowingUniversalAccess 配一个路径列表。Web 组件用 file 协议访问这些路径下的资源时,可以放开跨域访问。它的限制也写得很清楚:路径必须来自应用文件目录或资源目录对应的子目录,否则会抛 401。空列表则还是按 fileAccess 的规则走。
路径格式大致是这两类:
- 应用文件目录:通过 Context.filesDir 获取,比如
/data/storage/el2/base/files/example、/data/storage/el2/base/haps/entry/files/example - 应用资源目录:通过 Context.resourceDir 获取,比如
/data/storage/el1/bundle/entry/resource/resfile、/data/storage/el1/bundle/entry/resource/resfile/example
我这里怎么做的
这次用的是第二种。原因很简单:改动小,先把页面跑通,比一上来重构资源加载链路省事。
最开始 Web 组件里用的是 resource:// 去读资源:
Web({ : , : . })


