美文网首页ReactNative开发
React Native 编译打包的缓存问题

React Native 编译打包的缓存问题

作者: peaktan | 来源:发表于2021-02-06 22:03 被阅读0次

    时间过得真快,转眼间就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
    

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

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

    相关文章

      网友评论

        本文标题:React Native 编译打包的缓存问题

        本文链接:https://www.haomeiwen.com/subject/detatltx.html