Metro 缓存机制全解:本地缓存、远程缓存与 cacheStores 配置实战
构建工具移动开发CLI【免费下载链接】metro The JavaScript bundler for React Native项目地址https://gitcode.com/gh_mirrors/me/metro点击查看免费下载MetroReact Native 的 JavaScript 打包器通过将模块转换transformation结果缓存起来避免了源码或配置未变化时的重复计算从而显著加速构建。本文以官方文档 docs/Caching.md 为核心结合metro-cache、metro-config与metro三个包的真实源码系统讲解 Metro 的缓存工作原理、cacheStores配置方法、内置缓存存储的用法与参数以及如何实现自定义缓存存储帮助你在单机与团队场景下正确配置和调优缓存。一、缓存体系总览本地缓存与远程缓存Metro 在开箱状态下即使用本地缓存来存储已转换模块的结果关于转换阶段的概念可参考 docs/Concepts.md。得益于该缓存Metro 不需要重新转换每个模块——除非自上次转换以来该模块的源码或当前配置发生了变化。在本地缓存之外Metro 还支持远程缓存。对于大型团队和/或大型代码库远程缓存可以进一步减少本机构建远端变更所花费的时间从而大幅加速构建。官方文档提到这正是 Meta 内部使用 Metro 构建 React Native 应用的方式一个拥有成千上万个文件、数百名日常活跃工程师的代码库。典型的远程缓存部署方案一个标准的远程缓存配置通常包含三个环节准备一个团队专用的存储后端例如 S3 bucket。周期性运行metro build命令例如放在 CI 任务中来填充缓存在 Metro 配置中使用HttpStore或自定义的读写缓存存储。在开发机上配置 Metro 从缓存读取在 Metro 配置中使用HttpGetStore或自定义的只读缓存存储。metro build是 CLI 提供的构建命令其常用选项如下详见 docs/CLI.md选项别名说明取值outO输出 bundle 的文件名Stringplatformp打包的目标平台web、android、iosminifyz是否压缩 bundleBooleandevg是否生成开发版构建process.env.NODE_ENV developmentBooleanconfigc使用的metro.config.js路径Stringmax-workersj并行转换的 worker 数Numberproject-rootsP项目根目录Arraysource-map—是否生成 source mapBooleansource-map-url—source map 的地址Stringresolver-option—自定义 resolver 选项形式keyvalueArraytransform-option—自定义 transform 选项形式keyvalueArray也就是说CI 中一条类似metro build src/index.js --out dist/bundle.js --platform android的命令即可产出 bundle并在此过程中通过HttpStore把每个模块的转换结果写入远程缓存开发机上则通过HttpGetStore命中这些结果无需在本地重新转换。二、cacheStores配置本地优先、远程兜底Metro 缓存的核心配置项是cacheStores。官方文档明确建议本地缓存如FileStore应排在列表首位远程缓存如HttpStore紧随其后。这样排列的原因是 Metro 缓存读取的语义当 Metro 需要转换一个模块时它会先为该文件计算一个机器无关的缓存键然后按顺序尝试从每个 store 中读取。一旦拿到转换结果无论来自缓存还是重新计算它会将该结果写入所有对该键返回了null缓存未命中的 store。这一行为在 Cache.js 中体现得非常清楚Cache.get()顺序遍历#stores数组首次命中即返回Cache.set()则把值写入从第一个 store 起、直到命中该键的那个 store 为止的所有 store通过#hits这个WeakMap记录“哪个 store 命中了这个键”避免把已存在的值重复写回。此外Cache类为每次get/set记录日志日志项包含 store 名与十六进制键并通过action_result: hit | miss标记缓存命中与未命中。配置cacheStores有两种形式直接传入 store 实例数组或传入以metro-cache包导出对象为参数的函数。文档给出的函数形式示例如下// metro.config.js const os require(node:os); const path require(node:path); module.exports { cacheStores: ({ FileStore }) [ new FileStore({ root: path.join(os.tmpdir(), metro-cache), }), ], };注意FileStore、AutoCleanFileStore、HttpStore、HttpGetStore等类既可以从metro-cache包直接导入也可以通过cacheStores的函数形式MetroCache参数拿到后者避免了在配置文件中额外引入包依赖。配置解析层会在调用该函数时自动注入metro-cache的导出见 loadConfig.js 与测试 loadConfig-test.js。cachestores.config.js 是仓库中一个真实的函数形式配置示例module.exports { cacheStores: ({ FileStore }) { return [new FileStore({ root: __dirname })]; }, };如果不配置该选项Metro 的默认行为是仅使用一个临时目录下的FileStore。默认配置位于 defaults/index.jscacheStores: [ new FileStore({ root: path.join(os.tmpdir(), metro-cache), }), ],相关配置项还有两个值得关注cacheVersion默认1.0参与全局缓存键的计算。当你调整了会改变转换结果的配置时应提升该版本号使旧缓存失效详见 docs/Configuration.md。resetCache设为true时Metro 会在启动时重置转换缓存与文件映射缓存见 docs/Configuration.md。三、内置缓存存储逐个解析Metro 为cacheStores提供了若干内置实现源码位于 packages/metro-cache/src/stores统一从 packages/metro-cache/src/index.js 导出。FileStore({root})将缓存条目作为文件存放到root指定的目录下。从 FileStore.js 可以看出其磁盘布局#getFilePath(key: Buffer): string { return path.join( this.#root, key.slice(0, 1).toString(hex), // 键的第一个字节作为子目录 key.slice(1).toString(hex), // 剩余字节作为文件名 ); }即每个缓存键对应root/首字节 hex/其余字节 hex路径下的一个文件文件内容为 JSON 序列化的值如果值是Buffer则在前面加一个0x00字节作为类型标记读取时据此还原见 FileStore.js。写入时会自动递归创建目录读取时遇到ENOENT或 JSON 解析错误一律视为未命中返回nullclear()则会删除root下的全部 256 个子目录。AutoCleanFileStore()已弃用一个会定期清理旧条目的FileStore接受与FileStore相同的root参数另加两个选项intervalMs: number两次清理尝试之间的时间间隔毫秒默认10 分钟cleanupThresholdMs: number条目距上次修改至少多久才允许被删除毫秒默认3 天。对应源码见 AutoCleanFileStore.js默认值分别为10 * 60 * 1000与3 * 24 * 60 * 60 * 1000。文档与源码注释都明确标注该实现已弃用其实现不够高效缓存较大时可能产生大量冗余 I/O。官方建议改用你自己的清理脚本或使用基于监听watches、挂钩 get/set、实现 LRU 的自定义缓存存储。HttpStore(options)一个轻量级bare-bones的远程缓存客户端通过 HTTP/HTTPS 执行读取GET与写入PUT传输的是压缩后的缓存产物。其核心选项如下endpoint: string缓存服务器的基础 URL。文档给出的示例是HttpStore配http://www.example.com/endpoint时发出的请求形如http://www.example.com/endpoint/c083bff944879d9f528cf185eba0f496bc10a47d——即键的十六进制字符串直接拼在endpoint路径之后见 HttpStore.js 中path: ${path}/${key.toString(hex)}。timeout: number请求超时时间毫秒默认5000。family: 4 | 6与 Node.jshttp.request的family参数含义一致。cert、ca、keyHTTPS 选项直接透传给 Node.js 内置的 HTTPS 客户端。从源码看HttpStore还支持更多未在文档中展开的选项值得了解getOptions/setOptions可以为读、写分别指定不同的端点配置HttpStore.js例如读走只读端点、写走可写端点params: URLSearchParams、headers附加在请求 URL 与请求头上的额外参数additionalSuccessStatuses额外视为成功的 HTTP 状态码默认仅 2xx 与 404 特例maxAttempts、retryNetworkErrors、retryStatuses重试配置。重试基于exponential-backoff实现采用 full jitter最大延迟 30 秒仅在错误属于HttpError且状态码命中retryStatuses、或属于NetworkError且开启retryNetworkErrors时才重试HttpStore.jsproxy通过https-proxy-agent支持代理debug出错时在错误信息中附加响应体便于排查。在协议层面GET返回 404 视为未命中返回null返回 200 时响应体会被 gzip 解压再按“0x00前缀的 Buffer 或 JSON”规则还原PUT写入时用 gzip压缩级别 9压缩请求体。相关的HttpError带 HTTP 状态码与NetworkError分别定义在 HttpError.js 与 NetworkError.js。HttpGetStore(options)HttpStore的只读版本。它继承HttpStore的全部读能力但set()为空操作HttpGetStore.jsget()遇到HttpError或NetworkError时不抛出而是吞掉错误并返回null同时只发出一次process.emitWarning警告提示无法连接 HTTP 缓存HttpGetStore.js。这正是它适合放在开发机上的原因远程缓存不可用时开发构建不至于失败只是退化为本地计算。四、缓存键的计算与命中流程源码级理解缓存的粒度有助于正确配置。Metro 的缓存单位是单个模块的转换结果键的构造在 Transformer.js 中完成全局缓存键globalCacheKey基于cacheVersion、projectRoot与 transformer 配置计算Transformer.js若cacheStores为空数组缓存被禁用则全局缓存键为空串Cache.isDisabled在 Cache.js 中定义。部分键partialKey由全局缓存键、项目相对路径POSIX 分隔、asset URL 路径、以及dev、platform、minify、type等转换选项经stableHash计算得到Transformer.js。完整键fullKeypartialKey拼接模块内容的 SHA-1 后得到Transformer.js。也就是说同一个文件只要内容SHA-1没变、转换选项没变就能命中缓存而stableHash使用带 canonicalize 的 JSON 序列化加 MD5 实现机器无关的稳定哈希见 stableHash.js保证了不同机器之间缓存键一致、可共享远程缓存。命中后的流程是cache.get(fullKey)命中则直接使用结果未命中则交给workerFarm.transform()重新转换转换完成后cache.set()以 fire-and-forget 方式异步写回所有未命中该键的 storeTransformer.js。读取与写入失败会分别通过 reporter 上报cache_read_error/cache_write_error事件。五、自定义缓存存储cacheStores接收的是实现了以下接口的类的实例官方文档 docs/Caching.md 原样给出仓库中的类型定义见 types.jsinterface CacheStoreT: Buffer | JsonSerializable { // 从缓存读取条目未找到时返回 null get(key: Buffer): ?T | Promise?T; // 写入缓存条目只读存储可空操作 set(key: Buffer, value: T): void | Promisevoid; // 清空缓存如可行否则空操作 clear(): void | Promisevoid; } type JsonSerializable /* Any JSON-serializable value */;实现时有几点需要严格遵守缓存条目的值要么是Buffer实例要么是 JSON 可序列化的值内部结构两者均不指定对同一个缓存键get()必须返回与set()时相同类型的值例如不能写入 Buffer 却按 JSON 解析返回set与clear是“尽力而为”的只读存储直接空操作即可按需提供name属性或依赖类名用于Cache的日志标识Cache.js。如果你的远程存储无法直接支持按 key 读写例如对象存储需要额外索引可以仿照HttpGetStore的容错思路读取失败时返回null并告警让缓存不可用时退化为本地计算写入失败时则交由Cache.set()内部捕获——源码中set()会收集所有 store 的写失败并抛出AggregateErrorCache.js因此自定义 store 的set()建议在需要时自行吞掉可恢复错误避免影响主构建流程。六、实战完整的本地 远程缓存配置将以上内容组合起来一个面向团队场景的完整metro.config.js大致如下// metro.config.js const os require(node:os); const path require(node:path); module.exports { cacheStores: ({ FileStore, HttpStore, HttpGetStore }) [ // 1. 本地缓存优先目录置于系统临时目录 new FileStore({ root: path.join(os.tmpdir(), metro-cache), }), // 2. CI/写端完整的读写远程缓存客户端 new HttpStore({ endpoint: https://cache.example.com/metro, timeout: 5000, // HTTPS 双向认证所需选项如需要 // cert: ..., ca: ..., key: ..., // 可选读、写使用不同端点 // getOptions: { endpoint: https://cache-ro.example.com/metro }, // setOptions: { endpoint: https://cache.example.com/metro }, }), // 3. 开发机/只读端远程缓存不可用时静默降级 // new HttpGetStore({ endpoint: https://cache.example.com/metro }), ], };配置落地后CI 环境定期执行metro build entry --out bundle.js可配合--platform、--minify等选项用HttpStore将转换结果灌入团队缓存开发环境使用HttpGetStore或去掉写端 store构建时优先命中本地FileStore未命中则从远程缓存读取远程不可用时静默回退版本升级升级 Metro 或改变 transformer 配置后通过提升cacheVersion让旧缓存整体失效避免错误复用旧格式的缓存产物。结语Metro 的缓存体系本质上是“本地文件缓存兜底 可插拔的远程缓存提速”cacheStores决定存储后端cacheVersion与模块 SHA-1 决定缓存键的有效性Cache类决定多存储间的读写语义。把握住“本地优先、远程在后、读取失败降级”这三条原则再结合metro-cache内置实现与自定义接口就能在单机开发、CI 预热、团队共享三种场景下充分发挥 Metro 缓存的加速能力。相关实现细节可继续研读 packages/metro-cache、Transformer.js 以及 docs/Configuration.md 中的cacheStores小节。赞分享构建工具移动开发CLI【免费下载链接】metro The JavaScript bundler for React Native项目地址https://gitcode.com/gh_mirrors/me/metro点击查看免费下载相关推荐sbt构建缓存终极指南远程缓存和本地缓存配置详解sbt构建缓存终极指南远程缓存和本地缓存配置详解 在Scala项目开发中 sbt构建缓存 是提升开发效率的关键技术。无论是个人开发还是团队协作合理配置缓存构建工具Turborepo 缓存实战指南Monorepo 本地与远程构建缓存配置与调优Turborepo 缓存实战指南Monorepo 本地与远程构建缓存配置与调优 本文以 agents24 仓库中 developer essentials 插AI 插件AI 技能开发工具Cangjie/HarmonyOS-Examples 缓存机制实现本地缓存与网络缓存Cangjie/HarmonyOS Examples 缓存机制实现本地缓存与网络缓存 引言为什么需要缓存机制 在移动应用开发中缓存Cache机制是提示例工程上一篇突破移动边界Winlator技术对比与跨平台解决方案深度解析下一篇xh终极HTTP请求工具比HTTPie更快更友好的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

8192GB巨量狂飙 Kingston FURY G5固态硬盘:PCIe 5.0 NVMe 满速验证与 TaoToken 配置记录

8192GB巨量狂飙 Kingston FURY G5固态硬盘:PCIe 5.0 NVMe 满速验证与 TaoToken 配置记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 1:26:46 阅读更多 →
InterviewGuide 海量数据处理面试题精解(第 6–10 题):TopK 查询、位图判重、双堆求中位数与外排序实战

InterviewGuide 海量数据处理面试题精解(第 6–10 题):TopK 查询、位图判重、双堆求中位数与外排序实战

文档教程知识库 【免费下载链接】InterviewGuide 🔥🔥「InterviewGuide」是阿秀从校园->职场多年计算机自学过程的记录以及学弟学妹们计算机校招&秋招经验总结文章的汇总,包括但不限于C/C 、Golang、JavaScript、Vue、操作系统、数据结…

2026/10/12 1:26:46 阅读更多 →
C++ 小病毒让鼠标锁死:用 TaoToken 统一 Key 复现与防御实验

C++ 小病毒让鼠标锁死:用 TaoToken 统一 Key 复现与防御实验

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 1:26:46 阅读更多 →

最新新闻

具身智能创新原理(71):面向人机协作的复杂意图理解与多轮交互优化

具身智能创新原理(71):面向人机协作的复杂意图理解与多轮交互优化

前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”)是依托Transformer架构与“因式智能体”理论构建的通用视觉技术体系。它有机融合深度强化学习(DRL)、卷积神经网络&#xff08…

2026/10/12 2:14:15 阅读更多 →
具身智能创新原理(76):融合环境感知与自适应控制的协同架构研究

具身智能创新原理(76):融合环境感知与自适应控制的协同架构研究

前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”)是依托Transformer架构与“因式智能体”理论构建的通用视觉技术体系。它有机融合深度强化学习(DRL)、卷积神经网络&#xff08…

2026/10/12 2:14:15 阅读更多 →
具身智能创新原理(74):融合跨模态感知与协同推理的基础架构研究

具身智能创新原理(74):融合跨模态感知与协同推理的基础架构研究

前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”)是依托Transformer架构与“因式智能体”理论构建的通用视觉技术体系。它有机融合深度强化学习(DRL)、卷积神经网络&#xff08…

2026/10/12 2:14:15 阅读更多 →
具身智能创新原理(75):一种融合风险感知与防御机制的协同架构研究

具身智能创新原理(75):一种融合风险感知与防御机制的协同架构研究

前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”)是依托Transformer架构与“因式智能体”理论构建的通用视觉技术体系。它有机融合深度强化学习(DRL)、卷积神经网络&#xff08…

2026/10/12 2:14:15 阅读更多 →
具身智能创新原理(69):跨模态语义对齐的架构动态参照系建模研究

具身智能创新原理(69):跨模态语义对齐的架构动态参照系建模研究

前沿技术探索:TVA智能体(简称TVA) TVA智能体(亦称“AI智能体视觉”)是依托Transformer架构与“因式智能体”理论构建的通用视觉技术体系。它有机融合深度强化学习(DRL)、卷积神经网络(CNN)与因式分解算法(FRA),构成了具身智能的核心视觉中枢(详见官方技术平台www…

2026/10/12 2:14:15 阅读更多 →
ClusterFuzz 深度解析:Google 开源的可扩展分布式模糊测试基础设施

ClusterFuzz 深度解析:Google 开源的可扩展分布式模糊测试基础设施

应用安全后端开发工具 【免费下载链接】clusterfuzz Scalable fuzzing infrastructure. 项目地址: https://gitcode.com/gh_mirrors/cl/clusterfuzz 点击查看 免费下载 ClusterFuzz 是 Google 开源的可扩展模糊测试(fuzzing)基础设施&#x…

2026/10/12 2:13:15 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →