React Native 编译打包的缓存问题

时间过得真快,转眼间就2021年了,这段时间工作比较忙,但还是抽空将工作中的经验总结分享给大家,希望大家在新的一年里都能有所收获~

一、metro 的缓存机制

1、为什么要缓存

react-native 在执行 react-native start 或者 react-native bundle 命令的时候,都会有缓存。

目的其实很简单,metro 在打包的时候需要将 TSES6/7 的代码转换为 ES5 的目标代码。
那如果一个文件没有任何变更,这个时候我们就不需要去转换它了,所以 metro 设置了一套文件缓存机制来优化编译转换速度 。

2、两种缓存机制

metro 的缓存实现在 node_modules/metro-cache 中,主要有两种缓存机制:

  • 服务端缓存:HttpStore
  • 本地缓存:FileStore

服务端主要是通过服务器来缓存相关内容,优势是不用担心缓存的大小和时间限制,可以灵活的设置缓存策略,不过这个我们目前没有使用到,后期可以考虑。

metro 默认的缓存机制是 FileStore,这也是我们目前使用的缓存机制,FileStore 实际上就是将编译转换后的文件缓存起来,以便下一次编译的时候能够避免重复转换,加快编译速度。

3、FileStore 缓存原理

FileStore 缓存的原理其实很简单:

  • 缓存的key:表名 + 文件内容映射生成的 hash 值
  • 缓存的内容:转换后的文件内容

当执行转换的时候,如果发现文件的 hash 值存在,那么就说明文件内容没有发生变化,就不会去执行转换操作, 大大节省了编译时间。FileStore 为了避免 hash 碰撞,采用了分表存储,具体可以查看 FileStore.js 的源代码来了解更多。

FileStore分表缓存策略.png

二、metro 缓存到哪里去了

知道了 metro 的缓存机制,那么这个缓存到底存储在本地系统的什么位置呢?

查看 FileStore.js 源代码发现初始化 FileStore 时会传入一个 root 参数,这个 root 其实就是缓存存储的路径。所以我们只要知道 FileStore 在哪里初始化的,就能知道缓存的地址了。

FileStore构造函数.png
创建目录.png

在 start 的时候我们没有指定 metro 的配置,所以 metro 的配置都是从 node_modules/metro-config/defaults/index.js 中读取的默认配置,在这里可以看到缓存的初始化代码,如下:

cacheStores: [
    new FileStore({
      root: path.join(os.tmpdir(), "metro-cache")
    })
]

缓存路径为 os.tmpdir() 拼接上 "/metro-cache"

那这个 os.tmpdir() 是什么呢?os 是 node.js 的一个系统库,tempdir() 获取的是系统的临时目录,其值等于在 Linux 终端下执行如下命令获取的值:

echo $TMPDIR

最终得出缓存地址为:echo $TMPDIR 拼接上 "/metro-cache",大家可以自行尝试查看。

image2021-1-21_16-55-9.png

三、缓存导致的问题及解决方案

1、问题

react-native 的缓存会导致各种问题,常见的问题为更新了依赖库,团队中有的小伙伴能正常运行,有的缺报莫名其妙的错误,这是在执行 npm start 时缓存带来的问题,实际上执行 react-native bundle 打包也会有缓存问题,所以问题从大类来讲有以下两类:

1. 修改了依赖库,团队中有的小伙伴能正常运行,有的则报出莫名其妙的错误
2. react-native bundle 打包偶现 找不到 metro-cahce/T/xxxx 文件错误

这两类问题都是由于 metro 缓存导致的。

2、解决方案

既然是缓存问题,那么清除缓存就能够解决问题,有以下几种方案来清除缓存:

  1. 重启电脑tempdir 目录是一个临时目录,在重新电脑之后实际上就会被清除,所以 tempdir 目录下的 metro-cache 目录也会被清除
  2. 手动删除缓存:终端执行 echo $TMPDIR 获取 临时目录,再拼接上 metro-cache 得到缓存目录,手动删除 metro-cache 目录即可
  3. 自动删除缓存:metro打包提供了不少参数,其中就有一个清除缓存的参数,只需在执行 startbundle 时带上 --reset-cache即可自动删除缓存
react-native start --reset-cache
react-native bundle --reset-cache

删除缓存之后再次编译或者打包时都会变慢,所以一般情况下无需删除缓存。

本篇为原创文章,希望大家多多支持,转载请注明出处,谢谢~

推荐阅读更多精彩内容

  • 前言 metro是一种支持ReactNative的打包工具,我们现在也是基于他来进行拆包的。为了对bundle进行...
    LaxusJ阅读 4,970评论 1 51
  • 记录下自己在 RN 开发中遇到的一些问题。 RN 组件相关 TextInput Android 文字对齐问题 当 ...
    aJIEw阅读 1,678评论 0 2
  • 1、搭建开发环境。可参考 https://reactnative.cn/docs/getting-started/...
    骑着毛驴走起来阅读 1,484评论 0 0
  • 1.对于React-Native开发,仅仅有基础前端开发的知识是不够的,你还需要了解和掌握的有: • Node.j...
    glenlg阅读 145评论 0 1
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 4,522评论 16 21