适用人群:刚接触鸿蒙混合开发,希望基于
@magongshou/harmony-cordova快速搭建工程、跑通示例,但经常遇到"白屏、资源 404、Hostname 配错"等问题的同学。文章以"问题解决"为主,代码占比约 3/10,更多篇幅用于解释工程结构和排错思路。
1. 整体框架先搞清楚
在排查任何问题之前,先要知道 工程里有哪些层、谁加载谁:
- 原生层(ArkTS / Harmony 工程)
EntryAbility:应用入口,初始化 Web 引擎,加载首屏pages/Index。Index.ets:ArkUI 首屏,承载MainPageCordova 容器。
- 容器层(Cordova ArkTS 实现)
MainPage.ets:封装 ArkWeb WebView + Cordova 初始化 + 资源拦截。- Cordova 插件体系:
CordovaPlugin、PluginEntry等。
- Web 前端层(rawfile 静态资源)
rawfile/www/index.html:2048 入口页。css/、js/:样式与游戏逻辑。
1.1 框架结构图
EntryAbility Index.ets MainPage Cordova 容器 ArkWeb WebView rawfile/www/index.html css/style.css js/app.js
1.2 目录结构速览(简化)
text
entry/
src/main/ets/
entryability/EntryAbility.ets
pages/Index.ets
cordova/
src/main/ets/components/MainPage.ets
src/main/ets/components/CordovaPlugin.ets
src/main/resources/rawfile/www/
index.html
css/style.css
js/app.js
理解这张图后,很多"找不到文件""白屏"问题就有了排查顺序:
- 先看 原生是否加载到 Index。
- 再看 Index 是否渲染了 MainPage。
- 再看 MainPage 是否计算出正确的 src URL。
- 最后看 rawfile/www 是否有对应资源。
2. 工程搭建中的典型问题一览
2.1 问题:启动后直接白屏,日志里几乎没 Web 输出
现象:
- App 能启动,但始终是纯色背景。
- Logcat/IDE 日志中能看到
EntryAbility.onCreate,但很少有 Web 相关日志。
排查思路(整体 Flow):
否 是 否 是 否 是 启动后白屏 EntryAbility 是否执行 initializeWebEngine? 补充初始化 Web 引擎 windowStage.loadContent 是否加载 pages/Index? 检查路由/页面路径 Index.build 中是否渲染 MainPage? 修复 Index.ets UI 构建 进入 MainPage 初始化流程
2.2 关键代码:EntryAbility 正确初始化 Web 引擎
ts
// entry/src/main/ets/entryability/EntryAbility.ets
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { webview } from '@kit.ArkWeb';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 初始化 ArkWeb 引擎
webview.WebviewController.initializeWebEngine();
}
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
// 这里可以增加日志,方便排查
return;
}
});
}
}
排查要点:
- 确认
initializeWebEngine()是否被调用。 - 确认
loadContent('pages/Index')的 路径大小写 无误(ArkTS 区分大小写)。
3. Hostname / indexPage 配置导致的"资源 404"
在本项目的 Cordova 实现中,MainPage 会根据 Cordova 配置来计算最终加载 URL:
ts
// 逻辑示意(简化版)
aboutToAppear() {
// ... InitCordova 返回 JSON 字符串
let preferences: string = cordova.InitCordova(/* 参数省略 */);
let jsonConfig: object = JSON.parse(preferences) as object;
let arrayObject: Array<object> = jsonConfig['preferences'];
arrayObject.forEach((obj: object) => {
if (obj['name'] === 'Hostname') {
this.strTmpUrl = obj['value'];
}
});
if (this.indexPage == '') {
this.src = 'https://' + this.strTmpUrl + '/www/index.html';
} else {
// 自定义入口
}
}
3.1 常见错误 1:Hostname 与实际不匹配
症状:
- 运行时控制台里出现类似:
GET https://example.com/www/index.html 404
- 但你的实际 Hostname 并不是
example.com。
解决步骤:
- 找到 Cordova 的配置(通常在
config.xml或等效配置)中:- 确认
Hostname与代码一致,例如localhost、harmony.cordova.local等。
- 确认
- 若不确定,可在
MainPage.aboutToAppear中临时打印this.src:
ts
console.log('[MainPage] final src = ' + this.src);
最佳实践:开发阶段可以统一用类似:
Hostname = "harmony.cordova.local",方便识别。
3.2 常见错误 2:误以为可以直接改 this.src 为本地 file URL
错误示例:
ts
// ❌ 错误示意:直接写 file://
this.src = 'file:///data/storage/el2/base/files/www/index.html';
在 Cordova 实现中,已经通过自定义协议 + 资源拦截 帮你处理了 rawfile 映射,直接使用 https://{Hostname}/www/index.html 即可,不需要手动拼 file 路径。
4. rawfile 目录与资源路径检查
若 URL 是正确的 https://{Hostname}/www/index.html,但仍报 404 或部分资源丢失,通常出在 rawfile 目录结构。
4.1 检查最终打包路径
构建后,Web 静态资源应位于:
text
cordova/src/main/resources/rawfile/www/
index.html
css/style.css
js/app.js
容易出错的点:
www目录层级错了,比如:rawfile/index.html而不是rawfile/www/index.html。- CSS/JS 的相对路径写成了绝对路径,导致找不到资源。
4.2 index.html 中的资源路径写法
推荐写法(来自项目实际代码):
html
<link rel="stylesheet" href="css/style.css" />
...
<script src="js/app.js"></script>
不要写成类似:
html
<!-- ❌ 容易出错的写法 -->
<link rel="stylesheet" href="/css/style.css" />
<script src="/js/app.js"></script>
因为 /css/style.css 会被当成根路径,而不是相对于 www/。
5. Index.ets 未正确渲染 MainPage 的问题
即使 EntryAbility 和资源路径都 OK,如果 Index.ets 没有渲染 MainPage,Web 仍然不会出现。
5.1 正确的 Index.ets 写法(节选)
ts
// entry/src/main/ets/pages/Index.ets
import {
MainPage,
pageBackPress,
pageHideEvent,
pageShowEvent,
PluginEntry
} from '@magongshou/harmony-cordova/Index';
@Entry
@Component
struct Index {
cordovaPlugs: Array<PluginEntry> = [];
onPageShow() { pageShowEvent(); }
onBackPress() { pageBackPress(); return true; }
onPageHide() { pageHideEvent(); }
build() {
RelativeContainer() {
MainPage({
isWebDebug: false,
cordovaPlugs: this.cordovaPlugs
});
}
.height('100%')
.width('100%')
}
}
排查 checklist:
- 是否导入了
MainPage? build()中是否真的调用了MainPage?- 是否给
MainPage足够的宽高(100%)?
6. 总结:从框架到问题排查的路线图
我们把本文的排查路径整理成一张图,方便你在遇到问题时快速定位:
否 是 否 是 否 是 否 是 App 启动异常/白屏/404 EntryAbility 初始化正常? 检查 initializeWebEngine & loadContent Index.ets 是否渲染 MainPage? 补充 MainPage & 生命周期透传 MainPage 计算的 src 是否正确? 检查 Hostname & indexPage rawfile/www 目录结构正确? 调整 www/ 目录与资源路径 进一步检查插件/拦截逻辑
建议用法:
- 新建工程或迁移旧 Web 项目时,对照本文一节一节检查。
- 遇到白屏时,按"入口 → Index → MainPage → rawfile"顺序排查,不要一上来就怀疑 Web 代码。
有了这篇"地基"文章,你在阅读本仓库其他高级主题(自定义插件、性能优化等)时,会更清楚每一层到底在干什么,也更容易在出现问题时快速定位到具体环节。