..

修复 Metro SHA-1 错误:react-native-worklets Bundle Mode 补丁指南

启动 private-mind 项目的 iOS 构建时,Metro 报出以下错误,导致打包失败:

Failed to get the SHA-1 for:
/Users/.../node_modules/react-native-worklets/.worklets/2830240121133.js

本文记录该错误的根因和官方推荐的修复方案。

背景

react-native-workletsreact-native-reanimated 生态中的一个包,提供 Bundle Mode 能力。private-mind 项目通过 react-native-streamdown 间接依赖了它,并在 babel.config.js 中启用了:

['react-native-worklets/plugin', { bundleMode: true }]

Bundle Mode 下,worklets 插件会在 node_modules/react-native-worklets/.worklets/ 目录中动态生成 JS 文件。Metro 打包时先解析这些文件路径,再去计算 SHA-1 哈希——但在这两步之间,worklets 插件可能已经重新生成了文件。Metro 发现文件”消失了”,于是抛错。

这个问题的实质是 Metro 文件监听器 + worklets 动态生成之间的竞态条件

官方修复方案

react-native-worklets 仓库提供了针对 Metro 和 metro-runtime 的补丁文件:

private-mind 使用的 metro 版本是 0.83.7,最接近的官方补丁是 0.83.2。小版本兼容,直接应用即可。

1. 确认 metro 版本

yarn why metro | grep "metro@npm"

输出两行,其中一行是 Expo 引入的:

metro@npm:0.83.7, metro@npm:^0.83.3

2. 给 metro 打补丁

yarn patch metro@npm:0.83.7

记下输出的临时目录路径(例如 /private/var/folders/.../user/XXXXX),编辑其中的 src/node-haste/DependencyGraph.js,在 getOrComputeSha1 方法内 return 之前插入:

if (mixedPath.includes("react-native-worklets/.worklets/")) {
  const createHash = require("crypto").createHash;
  return {
    sha1: createHash("sha1")
      .update(performance.now().toString())
      .digest("hex"),
  };
}

这段代码的作用:当 Metro 尝试计算 .worklets/ 下文件的 SHA-1 时,直接返回一个基于 performance.now() 生成的虚拟哈希,跳过文件系统读取——从而避免了文件被删除导致的错误。

保存后提交补丁:

yarn patch-commit -s <临时目录路径>

yarn 会将补丁写入 .yarn/patches/,并自动在 package.json 中添加 resolutions 条目。

3. 给 metro-runtime 打补丁

yarn patch metro-runtime@npm:0.83.7

编辑 src/modules/HMRClient.js,在 inject 函数体开头(if (global.globalEvalWithSourceUrl) 之前)插入:

if (global.__workletsModuleProxy?.propagateModuleUpdate) {
  global.__workletsModuleProxy.propagateModuleUpdate(code, sourceURL);
}

这个补丁确保 Fast Refresh 时 worklets 模块变更能正确通过 proxy 传播。

保存并提交:

yarn patch-commit -s <临时目录路径>

4. 清理缓存并重启

rm -rf node_modules/react-native-worklets/.worklets/*
npx expo start --clear

总结

步骤 包名 作用
1 metro 跳过 .worklets/ 文件的 SHA-1 计算,消除竞态报错
2 metro-runtime 让 Fast Refresh 正确更新 worklets 模块
3 清缓存 清除旧的 worklets 生成文件,从干净状态开始

完成后 iOS 构建应能正常通过。

参考

标签: [ React Native  Metro  Expo  iOS  ]