Skip to content

Commit d28f397

Browse files
committed
Cache prebuilt iOS binaries in ~/Library/Caches/ReactNative
Currently, Hermes, ReactNativeDependencies, and ReactNativeCore tarballs are cached only inside the Pods/ directory. This means every clean `pod install` (or deleting the Pods folder) triggers a full re-download from Maven, even if the same version was already downloaded before. This adds a shared cache layer at ~/Library/Caches/ReactNative/. On first download, tarballs are saved to the shared cache. On subsequent pod installs, if the local Pods cache is empty but the shared cache has the tarball, it is copied locally instead of re-downloaded. This benefits: - Clean installs after deleting Pods/ - Multiple projects using the same React Native version - CI environments with a persistent home directory Added descriptive log messages for each scenario (local hit, shared cache hit, cache miss + download) to aid debugging.
1 parent e2f8b5a commit d28f397

3 files changed

Lines changed: 79 additions & 18 deletions

File tree

packages/react-native/scripts/cocoapods/rncore.rb

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -386,18 +386,36 @@ def self.download_nightly_rncore(react_native_path, version, configuration, dsym
386386
download_rncore_tarball(react_native_path, tarball_url, version, configuration, dsyms)
387387
end
388388

389+
def self.shared_cache_dir()
390+
return File.join(Dir.home, "Library", "Caches", "ReactNative")
391+
end
392+
389393
def self.download_rncore_tarball(react_native_path, tarball_url, version, configuration, dsyms = false)
390-
destination_path = configuration == nil ?
391-
"#{artifacts_dir()}/reactnative-core-#{version}#{dsyms ? "-dSYM" : ""}.tar.gz" :
392-
"#{artifacts_dir()}/reactnative-core-#{version}#{dsyms ? "-dSYM" : ""}-#{configuration}.tar.gz"
394+
filename = configuration == nil ?
395+
"reactnative-core-#{version}#{dsyms ? "-dSYM" : ""}.tar.gz" :
396+
"reactnative-core-#{version}#{dsyms ? "-dSYM" : ""}-#{configuration}.tar.gz"
397+
destination_path = "#{artifacts_dir()}/#{filename}"
398+
399+
if File.exist?(destination_path)
400+
rncore_log("Tarball #{filename} already exists in Pods. Skipping download.")
401+
return destination_path
402+
end
393403

394-
unless File.exist?(destination_path)
404+
`mkdir -p "#{artifacts_dir()}"`
405+
406+
cached_path = File.join(shared_cache_dir(), filename)
407+
if File.exist?(cached_path)
408+
rncore_log("Cache hit: copying #{filename} from shared cache (#{shared_cache_dir()})")
409+
FileUtils.cp(cached_path, destination_path)
410+
else
411+
rncore_log("Cache miss: downloading #{filename} from #{tarball_url}")
395412
# Download to a temporary file first so we don't cache incomplete downloads.
396-
rncore_log("Downloading ReactNativeCore-prebuilt #{dsyms ? "dSYMs " : ""}#{configuration ? configuration.to_s : ""} tarball from #{tarball_url} to #{Pathname.new(destination_path).relative_path_from(Pathname.pwd).to_s}")
397413
tmp_file = "#{artifacts_dir()}/reactnative-core.download"
398-
`mkdir -p "#{artifacts_dir()}" && curl "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
399-
else
400-
rncore_log("Using downloaded ReactNativeCore-prebuilt #{dsyms ? "dSYMs " : ""}#{configuration ? configuration.to_s : ""} tarball at #{Pathname.new(destination_path).relative_path_from(Pathname.pwd).to_s}")
414+
`curl "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
415+
# Save to shared cache for future use
416+
`mkdir -p "#{shared_cache_dir()}"`
417+
FileUtils.cp(destination_path, cached_path)
418+
rncore_log("Saved #{filename} to shared cache (#{shared_cache_dir()})")
401419
end
402420

403421
return destination_path

packages/react-native/scripts/cocoapods/rndependencies.rb

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,15 +232,36 @@ def self.podspec_source_download_prebuilt_nightly_tarball(version)
232232
return {:http => url}
233233
end
234234

235+
def self.shared_cache_dir()
236+
return File.join(Dir.home, "Library", "Caches", "ReactNative")
237+
end
238+
235239
def self.download_rndeps_tarball(react_native_path, tarball_url, version, configuration)
236-
destination_path = configuration == nil ?
237-
"#{artifacts_dir()}/reactnative-dependencies-#{version}.tar.gz" :
238-
"#{artifacts_dir()}/reactnative-dependencies-#{version}-#{configuration}.tar.gz"
240+
filename = configuration == nil ?
241+
"reactnative-dependencies-#{version}.tar.gz" :
242+
"reactnative-dependencies-#{version}-#{configuration}.tar.gz"
243+
destination_path = "#{artifacts_dir()}/#{filename}"
244+
245+
if File.exist?(destination_path)
246+
rndeps_log("Tarball #{filename} already exists in Pods. Skipping download.")
247+
return destination_path
248+
end
239249

240-
unless File.exist?(destination_path)
250+
`mkdir -p "#{artifacts_dir()}"`
251+
252+
cached_path = File.join(shared_cache_dir(), filename)
253+
if File.exist?(cached_path)
254+
rndeps_log("Cache hit: copying #{filename} from shared cache (#{shared_cache_dir()})")
255+
FileUtils.cp(cached_path, destination_path)
256+
else
257+
rndeps_log("Cache miss: downloading #{filename} from #{tarball_url}")
241258
# Download to a temporary file first so we don't cache incomplete downloads.
242259
tmp_file = "#{artifacts_dir()}/reactnative-dependencies.download"
243-
`mkdir -p "#{artifacts_dir()}" && curl "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
260+
`curl "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
261+
# Save to shared cache for future use
262+
`mkdir -p "#{shared_cache_dir()}"`
263+
FileUtils.cp(destination_path, cached_path)
264+
rndeps_log("Saved #{filename} to shared cache (#{shared_cache_dir()})")
244265
end
245266

246267
return destination_path

packages/react-native/sdks/hermes-engine/hermes-utils.rb

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,16 +236,38 @@ def download_stable_hermes(react_native_path, version, configuration)
236236
download_hermes_tarball(react_native_path, tarball_url, version, configuration)
237237
end
238238

239+
def shared_cache_dir()
240+
return File.join(Dir.home, "Library", "Caches", "ReactNative")
241+
end
242+
239243
def download_hermes_tarball(react_native_path, tarball_url, version, configuration)
240-
destination_path = configuration == nil ?
241-
"#{artifacts_dir()}/hermes-ios-#{version}.tar.gz" :
242-
"#{artifacts_dir()}/hermes-ios-#{version}-#{configuration}.tar.gz"
244+
filename = configuration == nil ?
245+
"hermes-ios-#{version}.tar.gz" :
246+
"hermes-ios-#{version}-#{configuration}.tar.gz"
247+
destination_path = "#{artifacts_dir()}/#{filename}"
248+
249+
if File.exist?(destination_path)
250+
hermes_log("Tarball #{filename} already exists in Pods. Skipping download.", :info)
251+
return destination_path
252+
end
243253

244-
unless File.exist?(destination_path)
254+
`mkdir -p "#{artifacts_dir()}"`
255+
256+
cached_path = File.join(shared_cache_dir(), filename)
257+
if File.exist?(cached_path)
258+
hermes_log("Cache hit: copying #{filename} from shared cache (#{shared_cache_dir()})", :info)
259+
FileUtils.cp(cached_path, destination_path)
260+
else
261+
hermes_log("Cache miss: downloading #{filename} from #{tarball_url}", :info)
245262
# Download to a temporary file first so we don't cache incomplete downloads.
246263
tmp_file = "#{artifacts_dir()}/hermes-ios.download"
247-
`mkdir -p "#{artifacts_dir()}" && curl "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
264+
`curl "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
265+
# Save to shared cache for future use
266+
`mkdir -p "#{shared_cache_dir()}"`
267+
FileUtils.cp(destination_path, cached_path)
268+
hermes_log("Saved #{filename} to shared cache (#{shared_cache_dir()})", :info)
248269
end
270+
249271
return destination_path
250272
end
251273

0 commit comments

Comments
 (0)