PageSourceSearch

https://reactnative.dev/assets/js/097db54f.dfd55996.js

js reactnative.dev collected 2026-09-24 07:16:23 UTC 12,321 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkreact_native_website=self.webpackChunkreact_native_website||[]).push([["12555"],{26731(e,i,n){n.r(i),n.d(i,{metadata:()=>o,default:()=>h,frontMatter:()=>r,contentTitle:()=>a,toc:()=>l,assets:()=>s});var o=JSON.parse('{"id":"build-speed","title":"Speeding up your Build phase","description":"Building your React Native app could be expensive and take several minutes of developers time.","source":"@site/versioned_docs/version-0.77/build-speed.md","sourceDirName":".","slug":"/build-speed","permalink":"/docs/0.77/build-speed","draft":false,"unlisted":false,"editUrl":"[{\\"label\\":\\"Edit page for next release\\",\\"href\\":\\"https://github.com/facebook/react-native-website/edit/main/docs/build-speed.md\\"},{\\"label\\":\\"Edit page for 0.77 release\\",\\"href\\":\\"https://github.com/facebook/react-native-website/edit/main/website/versioned_docs/version-0.77/build-speed.md\\"}]","tags":[],"version":"0.77","lastUpdatedAt":1755675953000,"frontMatter":{"id":"build-speed","title":"Speeding up your Build phase"},"sidebar":"docs","previous":{"title":"Performance Overview","permalink":"/docs/0.77/performance"},"next":{"title":"Optimizing Flatlist Configuration","permalink":"/docs/0.77/optimizing-flatlist-configuration"}}'),t=n(62540),c=n(43023);let r={id:"build-speed",title:"Speeding up your Build phase"},a,s={},l=[{value:"Build only one ABI during development (Android-only)",id:"build-only-one-abi-during-development-android-only",level:2},{value:"Use a compiler cache",id:"use-a-compiler-cache",level:2},{value:"Local caches",id:"local-caches",level:3},{value:"Xcode Specific Setup",id:"xcode-specific-setup",level:4},{value:"Using this approach on a CI",id:"using-this-approach-on-a-ci",level:4},{value:"Distributed caches",id:"distributed-caches",level:3}];function d(e){let i={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,c.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(i.p,{children:["Building your React Native app could be ",(0,t.jsx)(i.strong,{children:"expensive"})," and take several minutes of developers time.\nThis can be problematic as your project grows and generally in bigger organizations with multiple React Native developers."]}),"\n",(0,t.jsxs)(i.p,{children:["To mitigate this performance hit, this page shares some suggestions on how to ",(0,t.jsx)(i.strong,{children:"improve your build time"}),"."]}),"\n",(0,t.jsx)(i.h2,{id:"build-only-one-abi-during-development-android-only",children:"Build only one ABI during development (Android-only)"}),"\n",(0,t.jsxs)(i.p,{children:["When building your android app locally, by default you build all the 4 ",(0,t.jsx)(i.a,{href:"https://developer.android.com/ndk/guides/abis",children:"Application Binary Interfaces (ABIs)"})," : ",(0,t.jsx)(i.code,{children:"armeabi-v7a"}),", ",(0,t.jsx)(i.code,{children:"arm64-v8a"}),", ",(0,t.jsx)(i.code,{children:"x86"})," & ",(0,t.jsx)(i.code,{children:"x86_64"}),"."]}),"\n",(0,t.jsx)(i.p,{children:"However, you probably don't need to build all of them if you're building locally and testing your emulator or on a physical device."}),"\n",(0,t.jsxs)(i.p,{children:["This should reduce your ",(0,t.jsx)(i.strong,{children:"native build time"})," by a ~75% factor."]}),"\n",(0,t.jsxs)(i.p,{children:["If you're using the React Native CLI, you can add the ",(0,t.jsx)(i.code,{children:"--active-arch-only"})," flag to the ",(0,t.jsx)(i.code,{children:"run-android"})," command. This flag will make sure the correct ABI is picked up from either the running emulator or the plugged in phone. To confirm that this approach is working fine, you'll see a message like ",(0,t.jsx)(i.code,{children:"info Detected architectures arm64-v8a"})," on console."]}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{children:'$ yarn react-native run-android --active-arch-only\n\n[ ... ]\ninfo Running jetifier to migrate libraries to AndroidX. You can disable it using "--no-jetifier" flag.\nJetifier found 1037 file(s) to forward-jetify. Using 32 workers...\ninfo JS server already running.\ninfo Detected architectures arm64-v8a\ninfo Installing the app...\n'})}),"\n",(0,t.jsxs)(i.p,{children:["This mechanism relies on the ",(0,t.jsx)(i.co
1de,{children:"reactNativeArchitectures"})," Gradle property."]}),"\n",(0,t.jsx)(i.p,{children:"Therefore, if you're building directly with Gradle from the command line and without the CLI, you can specify the ABI you want to build as follows:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{children:"$ ./gradlew :app:assembleDebug -PreactNativeArchitectures=x86,x86_64\n"})}),"\n",(0,t.jsx)(i.p,{children:"This can be useful if you wish to build your Android App on a CI and use a matrix to parallelize the build of the different architectures."}),"\n",(0,t.jsxs)(i.p,{children:["If you wish, you can also override this value locally, using the ",(0,t.jsx)(i.code,{children:"gradle.properties"})," file you have in the ",(0,t.jsx)(i.a,{href:"https://github.com/facebook/react-native/blob/19cf70266eb8ca151aa0cc46ac4c09cb987b2ceb/template/android/gradle.properties#L30-L33",children:"top-level folder"})," of your project:"]}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{children:"# Use this property to specify which architecture you want to build.\n# You can also override it from the CLI using\n# ./gradlew <task> -PreactNativeArchitectures=x86_64\nreactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64\n"})}),"\n",(0,t.jsxs)(i.p,{children:["Once you build a ",(0,t.jsx)(i.strong,{children:"release version"})," of your app, don't forget to remove those flags as you want to build an apk/app bundle that works for all the ABIs and not only for the one you're using in your daily development workflow."]}),"\n",(0,t.jsx)(i.h2,{id:"use-a-compiler-cache",children:"Use a compiler cache"}),"\n",(0,t.jsxs)(i.p,{children:["If you're running frequent native builds (either C++ or Objective-C), you might benefit from using a ",(0,t.jsx)(i.strong,{children:"compiler cache"}),"."]}),"\n",(0,t.jsx)(i.p,{children:"Specifically you can use two type of caches: local compiler caches and distributed compiler caches."}),"\n",(0,t.jsx)(i.h3,{id:"local-caches",children:"Local caches"}),"\n",(0,t.jsx)(i.admonition,{type:"info",children:(0,t.jsxs)(i.p,{children:["The following instructions will work for ",(0,t.jsx)(i.strong,{children:"both Android & iOS"}),".\nIf you're building only Android apps, you should be good to go.\nIf you're building also iOS apps, please follow the instructions in the ",(0,t.jsx)(i.a,{href:"#xcode-specific-setup",children:"Xcode Specific Setup"})," section below."]})}),"\n",(0,t.jsxs)(i.p,{children:["We suggest to use ",(0,t.jsx)(i.a,{href:"https://ccache.dev/",children:(0,t.jsx)(i.strong,{children:"ccache"})})," to cache the compilation of your native builds.\nCcache works by wrapping the C++ compilers, storing the compilation results, and skipping the compilation\nif an intermediate compilation result was originally stored."]}),"\n",(0,t.jsxs)(i.p,{children:["Ccache is available in the package manager for most operating systems. On macOS, we can install ccache with ",(0,t.jsx)(i.code,{children:"brew install ccache"}),".\nOr you can follow the ",(0,t.jsx)(i.a,{href:"https://github.com/ccache/ccache/blob/master/doc/INSTALL.md",children:"official installation instructions"})," to install from source."]}),"\n",(0,t.jsxs)(i.p,{children:["You can then do two clean builds (e.g. on Android you can first run ",(0,t.jsx)(i.code,{children:"yarn react-native run-android"}),", delete the ",(0,t.jsx)(i.code,{children:"android/app/build"})," folder and run the first command once more). You will notice that the second build was way faster than the first one (it should take seconds rather than minutes).\nWhile building, you can verify that ",(0,t.jsx)(i.code,{children:"ccache"})," works correctly and check the cache hits/miss rate ",(0,t.jsx)(i.code,{children:"ccache -s"})]}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{children:"$ ccache -s\nSummary:\n  Hits:             196 /  3068 (6.39 %)\n    Direct:           0 /  3068 (0.00 %)\n    Preprocessed:   196 /  3068 (6.39 %)\n  Misses:          2872\n    Direct:        3068\n    Preprocessed:  2872\n  Uncacheable:        1\nPrimary storage:\n  Hits:             196 /  6136 (3.19 %)\n  Misses:          5940\n  Cache size (GB): 0.60 / 20.00 (3.00 %)\n"})}
1),"\n",(0,t.jsxs)(i.p,{children:["Note that ",(0,t.jsx)(i.code,{children:"ccache"})," aggregates the stats over all builds. You can use ",(0,t.jsx)(i.code,{children:"ccache --zero-stats"})," to reset them before a build to verify the cache-hit ratio."]}),"\n",(0,t.jsxs)(i.p,{children:["Should you need to wipe your cache, you can do so with ",(0,t.jsx)(i.code,{children:"ccache --clear"})]}),"\n",(0,t.jsx)(i.h4,{id:"xcode-specific-setup",children:"Xcode Specific Setup"}),"\n",(0,t.jsxs)(i.p,{children:["To make sure ",(0,t.jsx)(i.code,{children:"ccache"})," works correctly with iOS and Xcode, you need to enable React Native support for ccache in ",(0,t.jsx)(i.code,{children:"ios/Podfile"}),"."]}),"\n",(0,t.jsxs)(i.p,{children:["Open ",(0,t.jsx)(i.code,{children:"ios/Podfile"})," in your editor and uncomment the ",(0,t.jsx)(i.code,{children:"ccache_enabled"})," line."]}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-ruby",metastring:'title="Ruby"',children:"  post_install do |installer|\n    # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202\n    react_native_post_install(\n      installer,\n      config[:reactNativePath],\n      :mac_catalyst_enabled => false,\n      # TODO: Uncomment the line below\n      :ccache_enabled => true\n    )\n  end\n"})}),"\n",(0,t.jsx)(i.h4,{id:"using-this-approach-on-a-ci",children:"Using this approach on a CI"}),"\n",(0,t.jsxs)(i.p,{children:["Ccache uses the ",(0,t.jsx)(i.code,{children:"/Users/$USER/Library/Caches/ccache"})," folder on macOS to store the cache.\nTherefore you could save & restore the corresponding folder also on CI to speedup your builds."]}),"\n",(0,t.jsx)(i.p,{children:"However, there are a couple of things to be aware:"}),"\n",(0,t.jsxs)(i.ol,{children:["\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:["On CI, we recommend to do a full clean build, to avoid poisoned cache problems. If you follow the approach mentioned in the previous paragraph, you should be able to parallelize the native build on 4 different ABIs and you will most likely not need ",(0,t.jsx)(i.code,{children:"ccache"})," on CI."]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.code,{children:"ccache"})," relies on timestamps to compute a cache hit. This doesn't work well on CI as files are re-downloaded at every CI run. To overcome this, you'll need to use the ",(0,t.jsx)(i.code,{children:"compiler_check content"})," option which relies instead on ",(0,t.jsx)(i.a,{href:"https://ccache.dev/manual/4.3.html",children:"hashing the content of the file"}),"."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(i.h3,{id:"distributed-caches",children:"Distributed caches"}),"\n",(0,t.jsx)(i.p,{children:"Similar to local caches, you might want to consider using a distributed cache for your native builds.\nThis could be specifically useful in bigger organizations that are doing frequent native builds."}),"\n",(0,t.jsxs)(i.p,{children:["We recommend to use ",(0,t.jsx)(i.a,{href:"https://github.com/mozilla/sccache",children:"sccache"})," to achieve this.\nWe defer to the sccache ",(0,t.jsx)(i.a,{href:"https://github.com/mozilla/sccache/blob/main/docs/DistributedQuickstart.md",children:"distributed compilation quickstart"})," for instructions on how to setup and use this tool."]})]})}function h(e={}){let{wrapper:i}={...(0,c.R)(),...e.components};return i?(0,t.jsx)(i,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},43023(e,i,n){n.d(i,{R:()=>r,x:()=>a});var o=n(63696);let t={},c=o.createContext(t);function r(e){let i=o.useContext(c);return o.useMemo(function(){return"function"==typeof e?e(i):{...i,...e}},[i,e])}function a(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),o.createElement(c.Provider,{value:i},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.