<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Viktor Benei</title>
    <description>The latest articles on DEV Community by Viktor Benei (@vbenei).</description>
    <link>https://dev.to/vbenei</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1425775%2Fbb7a1078-b813-4e4c-a005-14c7f86b3d6c.png</url>
      <title>DEV Community: Viktor Benei</title>
      <link>https://dev.to/vbenei</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vbenei"/>
    <language>en</language>
    <item>
      <title>How Build Cache for React Native works: caching the C++ your CI keeps recompiling</title>
      <dc:creator>Viktor Benei</dc:creator>
      <pubDate>Wed, 08 Jul 2026 12:04:27 +0000</pubDate>
      <link>https://dev.to/vbenei/how-build-cache-for-react-native-works-caching-the-c-your-ci-keeps-recompiling-2ke</link>
      <guid>https://dev.to/vbenei/how-build-cache-for-react-native-works-caching-the-c-your-ci-keeps-recompiling-2ke</guid>
      <description>&lt;p&gt;React Native projects compile twice. There's the platform layer you think about - Kotlin/Java on Android, Swift/Objective-C on iOS - and underneath it a shared &lt;strong&gt;C++ foundation&lt;/strong&gt;: Hermes, Folly, ReactCommon, the turbo modules. On CI, that C++ gets recompiled from scratch on every single build.&lt;/p&gt;

&lt;p&gt;You don't feel it locally because your incremental builds reuse the previous output. But CI starts from a clean clone every time, so it pays the full C++ compilation cost on every run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Gradle and Xcode caching don't save you here
&lt;/h2&gt;

&lt;p&gt;Both Gradle and Xcode ship their own caching. The problem is what they &lt;em&gt;don't&lt;/em&gt; cover. The React Native Android plugin declares its C++ compilation tasks as &lt;strong&gt;non-cacheable&lt;/strong&gt;, so Gradle's build cache skips right over them - every clean clone re-compiles every translation unit from scratch.&lt;/p&gt;

&lt;p&gt;So you can have Gradle caching fully dialed in and still watch minutes disappear into &lt;code&gt;clang&lt;/code&gt; on every CI run.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually caches C++: ccache with remote storage
&lt;/h2&gt;

&lt;p&gt;The tool for the job is &lt;a href="https://ccache.dev/" rel="noopener noreferrer"&gt;&lt;code&gt;ccache&lt;/code&gt;&lt;/a&gt; - but with a twist. A local ccache directory dies with your CI runner. To get real value you need &lt;strong&gt;remote&lt;/strong&gt; storage so a cache entry produced by one build is available to the next build on a different machine.&lt;/p&gt;

&lt;p&gt;On Android you point CMake at ccache:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;CMAKE_CXX_COMPILER_LAUNCHER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ccache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hard part is getting ccache to speak to a remote backend reliably. In our case we bridged ccache's wire protocol to a gRPC storage backend with a small Go process that ccache talks to over a Unix socket, translating remote read/write requests in real time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bringing it together
&lt;/h2&gt;

&lt;p&gt;A full RN pipeline ends up with three caching systems working in concert:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Gradle build cache&lt;/strong&gt; for JVM compilation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Xcode's LLVM Content Addressable Storage&lt;/strong&gt; for Apple platforms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ccache + remote storage&lt;/strong&gt; for the C++ layer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On Bitrise this is one command - &lt;code&gt;bitrise-build-cache activate react-native&lt;/code&gt; - which installs ccache and sets the environment up for you, then you monitor hit rates in Insights. But the mechanics above apply to any RN CI setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does it actually move the needle?
&lt;/h2&gt;

&lt;p&gt;From private beta teams:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;iOS&lt;/strong&gt; team: &lt;strong&gt;9m 35s → 5m 28s&lt;/strong&gt; (~43% faster)&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;multi-platform&lt;/strong&gt; team: Android &lt;strong&gt;~17m → ~9m&lt;/strong&gt; (~46%), iOS &lt;strong&gt;~10m 50s → ~6m 30s&lt;/strong&gt; (~40%)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Read the full writeup
&lt;/h2&gt;

&lt;p&gt;The full post goes deeper into the storage-helper design and the setup - &lt;a href="https://bitrise.io/blog/post/how-build-cache-for-react-native-works-caching-the-cpp-your-ci-keeps-recompiling" rel="noopener noreferrer"&gt;How Build Cache for React Native works: caching the C++ your CI keeps recompiling&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Full disclosure: I work at Bitrise. The C++/ccache mechanics here apply to any React Native CI setup, not just ours.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>cpp</category>
      <category>performance</category>
      <category>reactnative</category>
    </item>
  </channel>
</rss>
