HarmonyKit | 鸿蒙开发:hvigor 缓存机制与问题排查手册

📅 发布时间:2026/7/12 18:23:51
HarmonyKit | 鸿蒙开发:hvigor 缓存机制与问题排查手册 HarmonyKit | 鸿蒙开发hvigor 缓存机制与问题排查手册引言缓存是性能的源泉也是问题的温床HarmonyKit 开发过程中约有 20% 的诡异 bug最终定位到了 hvigor 缓存问题。这类 bug 的共同特征是代码逻辑完全正确、语法没有问题、昨天还能正常构建、今天突然就报错了。当你遇到这种变量型 bugissue only reproducible sometimes第一个怀疑对象就应该是缓存。这篇文章基于 HarmonyKit 项目中实际遇到并解决的 7 个缓存相关案例系统梳理 hvigor 的缓存体系、缓存失效的触发条件、排查步骤和清理策略。项目仓库https://atomgit.com/VON-/harmony-kithvigor 缓存体系全景hvigor 的缓存分布在三个位置各自缓存不同类型的数据第一层.hvigor/cache/构建引擎缓存.hvigor/cache/ ├── file-cache.json # 源文件哈希缓存 ├── last-build-info.json # 上次构建的快照信息 ├── project-config.json # 项目配置的解析结果缓存 ├── task-cache.json # 构建任务的执行结果缓存 └── meta.json # 缓存版本和兼容性元数据这层缓存的职责是避免重复工作。如果文件 A 在上次构建后没有变化hvigor 从file-cache.json中检测到哈希值一致直接跳过对该文件的编译——即使构建模式从 debug 切换到 release只要文件本身没变。last-build-info.json记录了上次构建的环境快照SDK 版本、模块列表、构建模式、时间戳。每次新构建开始时hvigor 对比当前环境与快照判断是否需要进行某些全局性的重新处理如重新解析依赖图、重新处理所有资源。第二层.hvigor/dependencyMap/依赖图缓存.hvigor/dependencyMap/ ├── oh-package.json5 # 项目级依赖的解析结果 ├── dependencyMap.json5 # 模块间依赖关系图 └── entry/ └── oh-package.json5 # entry 模块的依赖解析结果依赖图缓存的职责是快速确定受影响范围。当文件 A 被标记为脏因为内容变化hvigor 查询依赖图找出所有直接或间接 import 文件 A 的其他文件将这些文件也标记为脏。依赖图缓存的重要性HarmonyKit 的ToolItem.ets被 Index.ets 和 ToolCard.ets 引用。没有依赖图缓存hvigor 需要通过 AST 分析每个文件的 import 关系来判断影响范围——这在 20 个文件的项目中可能很快但在 200 个文件的项目中就变得昂贵了。第三层.hvigor/outputs/records/构建记录缓存.hvigor/outputs/records/ └── performance-recorder.json # 构建性能追踪记录这个文件记录了每次构建的各阶段耗时用于性能分析和 regressions 检测。它不直接影响构建正确性但对性能优化很有价值。第四层.hvigor/report/构建报告.hvigor/report/ ├── report-202607051507059470.json ├── report-202607051502171150.json └── ...每次构建生成一个报告文件包含构建过程的详细信息。主要用于 CI 环境的构建结果分析和历史对比。本地开发时一般不需要关注。缓存失效的五种触发场景场景一修改 hvigor-config.json5任何对hvigor/hvigor-config.json5的修改都应该触发缓存重置。但实际行为取决于修改的内容修改execution.parallel、execution.typeCheck不影响文件缓存和依赖图但影响编译过程的执行方式。hvigor 通常能正确处理增量。修改modelVersion标记大版本变更hvigor 应自动执行全量重建。修改dependencies影响插件加载需要重启 daemon 才能生效。最佳实践修改hvigor-config.json5后手动执行一次hvigorw clean hvigorw assembleHap。不要依赖 hvigor 的自动缓存失效判断。场景二切换 SDK 版本从 API 18 切换到 API 22 时所有缓存的类型信息和编译配置都过时了。hvigor 理论上应该检测到targetSdkVersion的变化并触发全量重建但在实际中不总是可靠。HarmonyKit 的迁经验切换到 API 22 时第一次增量编译通过了但运行时出现了 API 行为变化导致的崩溃。执行全量清理重建后问题消失。rm-rf.hvigor entry/build hvigorw --no-daemon assembleHap场景三重命名或移动源文件如果你重命名了RegexTester.ets为RegexTool.etshvigor 的缓存中仍然记录着旧文件RegexTester.ets的哈希值和编译状态。新的RegexTool.ets被当作新文件编译但旧的缓存记录可能会导致编译器报错找不到pages/tools/RegexTester——因为main_pages.json仍然引用旧路径依赖图缓存过时——引用RegexTester的 import 语句没有被更新最佳实践文件重命名后在 IDE 中使用Refactor Rename功能支持的话或者手动执行一次hvigorw clean。场景四Git 分支切换后构建异常当你在 feature 分支上修改了多个文件切换到 develop 分支时文件内容变了但.hvigor/cache/中的哈希值还是 feature 分支的。hvigor 通过文件修改时间戳辅助判断——切换分支会更新文件时间戳通常能正确触发重编译。但偶发情况下Git 操作可能保留文件时间戳取决于git checkout的行为和文件系统实现导致 hvigor 误判文件未变化。最佳实践gitcheckout develop hvigorw clean hvigorw assembleHap场景五异常中断的构建如果在构建过程中按下 CtrlC 强制中断或者在 DevEco Studio 中点了 Stop部分中间文件可能处于不一致状态。典型的例子entry/build/intermediates/中的中间产物只写了一半.hvigor/cache/task-cache.json记录了某个任务执行中但实际已中断daemon 进程仍然运行但内部状态不一致这种情况的症状是上次能构建CtrlC 后就不行了。修复方案# 第一级修复hvigorw clean hvigorw assembleHap# 如果仍然失败第二级修复rm-rf.hvigor entry/build hvigorw--stop# 停止 daemonhvigorw --no-daemon assembleHap最致命的缓存问题.hvigor 递归生成这是 HarmonyKit 开发中遇到的最诡异也最具破坏性的缓存问题。现象在entry/src/main/ets/pages/tools/目录下出现了一个.hvigor子目录其中又包含cache/、dependencyMap/等结构。更糟糕的情况.hvigor目录递归嵌套——.hvigor里面还有个.hvigor导致目录树无限扩展最终触发文件系统的递归限制编译报错Too many open files。根因hvigor daemon 在扫描源码目录构建依赖图时需要确定哪些目录是模块源码目录和哪些目录是缓存目录。正常情况下daemon 从项目根目录的build-profile.json5中读取modules[].srcPath来确定源码目录。但当 daemon 进程异常重启或者两个 DevEco Studio 实例同时运行时daemon 的工作目录可能被错误设置。如果 daemon 的当前工作目录指向了entry/src/main/ets/而不是项目根目录它将源码目录识别为./即当前目录将缓存输出到./.hvigor/即entry/src/main/ets/.hvigor/。这之后下一次构建时 daemon 扫描源码目录发现.hvigor子目录将其中的文件也纳入编译范围——包括缓存文件JSON和可能被递归包含的更多文件。排查与修复# 1. 定位所有不在项目根目录的 .hvigor 目录findentry/-name.hvigor-typed# 2. 删除所有错误的 .hvigor 目录findentry/-name.hvigor-typed-execrm-rf{}# 3. 检查是否有递归嵌套导致的超大深层目录findentry/-maxdepth50-typed|wc-l# 如果行数异常大超过几百说明可能仍有残留# 4. 彻底清理并重建rm-rf.hvigor entry/build hvigorw--stopkillallnode# 极端情况杀掉所有 Node 进程hvigorw --no-daemon clean hvigorw assembleHap预防及时清理过期 daemon开发完成后用hvigorw --stop停止 daemon不要让它一直在后台运行避免多实例不要同时打开两个 DevEco Studio 窗口指向同一个项目定期全量重建每周执行一次rm -rf .hvigor entry/build hvigorw assembleHap可以避免缓存问题的积累缓存问题排查的通用流程遇到代码明明对但构建失败的问题按以下步骤排查Step 1: 确认不是代码问题# 检查语法是否完全正确# 在 DevEco Studio 中查看 Problems 面板# 确认不是 ArkTS 严格模式导致的类型错误Step 2: 清理应用级缓存尝试保留 daemonhvigorw clean hvigorw assembleHapStep 3: 清理所有缓存包括 daemonrm-rf.hvigor entry/build hvigorw--stophvigorw --no-daemon assembleHapStep 4: 终极清理完全从零开始rm-rf.hvigor entry/build oh_modules/.hvigor .idea hvigorw--stopkillallnodeohpminstallhvigorw --no-daemon assembleHapStep 5: 检查环境问题# 验证 SDK 安装是否正确hdc list targets# 验证 Node.js 版本node--version# 验证 ohpm 版本ohpm--version# 检查磁盘空间df-h.大多数缓存问题在 Step 2 或 Step 3 就能解决。如果问题持续到 Step 4 仍然存在那很可能不是缓存问题需要回到代码或环境检查。build 目录什么时候该删entry/build/目录包含的是构建产物而非缓存。删除它是安全且常见的操作rm-rfentry/build应该删除 build/ 的场景切换 buildModedebug → release 或反过来修改了module.json5中的配置如 abilities、permissions修改了资源文件resources/目录下的内容修改了签名配置构建后的 HAP 安装到设备上行为异常不需要删除 build/ 的场景仅修改了.ets源文件增量编译会正确处理仅修改了main_pages.json中的页面列表删除 build/ vs 删除 .hvigor/ 的区别删除build/清理构建产物但保留编译缓存下次构建回退到增量编译的缓存有效但产物缺失状态重新生成所有中间和最终产物但不需要重新编译未变化的源文件删除.hvigor/清理编译缓存下次构建是全量编译所有文件重新编译删除两者完全的从零开始构建对于日常开发先试hvigorw clean不行再删.hvigor/是最有效率的排查路径。缓存与 CI/CD 的交互在 CI/CD 环境中缓存的策略不同应该跨构建保留的缓存oh_modules/如果oh-package.json5没有变化复用已安装的依赖可以节省安装时间~/.ohpm/cache/ohpm 的全局缓存目录位于用户目录下应该每次构建清理的缓存.hvigor/cache/CI 环境中的文件路径可能每次都不同如临时目录entry/build/CI 的每次构建都应该是干净的CI 配置示例-name:Buildrun:|# 清理构建产物保留依赖缓存 rm -rf entry/build .hvigor/cache# 如果 oh-package.json5 变化了才重装依赖ohpm install# 全量干净构建hvigorw--no-daemon assembleHap-p buildModereleaseCI 中使用--no-daemon是因为每次 CI 运行结束后环境被销毁daemon 的常驻没有意义反而可能因为残留进程导致下一次 CI 运行出现问题。缓存规模与项目规模的关系HarmonyKit 是一个小型项目约 25 个 .ets 文件~2000 行代码缓存体积不到 5MB。但大型鸿蒙项目的缓存体积可能达到数百 MB。缓存规模和项目规模的对应关系经验值项目规模.ets 文件数.hvigor/ 体积构建时间全量构建时间增量小型如 HarmonyKit 50 10 MB~15s~4s中型50-20010-50 MB~30s~8s大型200-100050-200 MB~90s~20s超大型 1000 200 MB2-5 min~40s对于中型及以上项目缓存的重要性显著提升——全量构建可能需要 90 秒甚至更久增量编译是日常开发体验的生命线。因此正确的缓存管理在大型项目中不是可选优化而是开发可行性的前提。结语缓存问题是所有构建系统都面临的经典难题——你既要缓存来提高性能又因为缓存引入了一致性问题。hvigor 作为相对年轻的构建系统在缓存策略上仍在迭代优化。对开发者来说最重要的不是记住每个缓存文件的作用而是建立一套排查习惯遇到构建问题先问是不是缓存的问题按清理层级从最轻到最重逐步排查。大多数时候hvigorw clean就是你需要的全部修复。项目仓库https://atomgit.com/VON-/harmony-kit