I found that the React Native official documentation missed some details about the Hermes bytecode and how to ensure that Hermes was enabled correctly. Let me explain it in an easy way so that you can optimize your app’s performance with respect to the Hermes engine.
Let’s take a look at what we will learn in this article in a nutshell 👇
Since you are going to work with new architecture, you should understand the full flow of it. Therefore, I strongly recommend that you read this article first and then come back here.
Article link: React Native New Architecture in depth (Hermes relation in New Architecture)
If you already have enough knowledge about the new architecture of React Native and how its components (Hermes, JSI, Turbo, Fabric, etc) are interconnected, you can skip the article above. You can proceed to the next section.
Release mode is a way of building and running your React Native app that optimizes its performance and size. It also enables some features that are not available in debug mode, such as Hermes, ProGuard, and signing.
In release mode, your app bundles all the JavaScript needed to run into an AAB (Android App Bundle) or an IPA (iOS App Store Package) file. This reduces the app size and makes it faster to load and run.
Release mode helps you to test your app in a realistic environment before publishing it to the app stores. It also helps you to avoid some errors or bugs that may occur only in debug mode.
For Android run this bellow command for Android release build
npx react-native run-android --mode=release
NOTE: You need to have keystore file inside yourApp/android/app this location of your app to get the release command success.
For iOS run this bellow command for iOS release build
npx react-native run-ios --configuration Release
Hermes is a JavaScript engine optimized for fast start-up of React Native apps. It features ahead-of-time static optimization and compact bytecode.
Bytecode is a low-level representation of JavaScript code that can be executed by the engine faster than the original source code. Hermes bytecode is stored in .hbc files that are generated during the app build process.
When you enable Hermes in your React Native app, your JavaScript code is compiled to Hermes bytecode and bundled into your app. This reduces the app size and improves the start-up time and memory usage.
According to the official documentation, Hermes is the default engine as of React Native 0.70. This means that all new projects starting on v0.70 will have Hermes enabled by default.
A HermesInternal global variable will be available in JavaScript that can be used to verify that Hermes is in use:
const isHermes = () => !!global.HermesInternal;
I applied it like bellow 👇
Output 👇
If you are using a non-standard way of loading the JS bundle, it is possible that the HermesInternal variable is available but you aren't using the highly optimised pre-compiled bytecode. Confirm that you are using the .hbc file and also benchmark the before/after as detailed below.
At the beginning of this article, we saw how to create a bundle release for both Android & iOS. For Android, when you apply that release command then immediately after successfully completion of release build you will find an .apk file created under this bellow file path location.
yourApp/android/app/build/outputs/apk/release
The file name should look something like this: “app-arm64-v8a-release.apk” or similar like this.
But wait, there’s more! You can actually do something amazing with this file 💁♂️
All you need to do is change the file extension from .apk to .ZIP like this 👇
Then extract that ZIP folder using any Unarchiver app. Now open that unarchived folder & go to “assets” folder.
Inside that “assets” folder, if you find a file “index.android.bundle” then open your terminal under “assets” folder and then paste the bellow command in terminal 👇
file index.android.bundle
After running the command, you will see like bellow 👇
It shows that the bundle was created by Hermes engine. Great, you are using hbc (Hermes Bytecode) file 💁♂️
Hermes is the default engine as of React Native 0.70. This section explains how to enable Hermes on older versions of React Native. First, ensure you’re using at least version 0.60.4 of React Native to enable Hermes on Android or 0.64 of React Native to enable Hermes on iOS.
If you have an existing app based on an earlier version of React Native, you will have to upgrade it first. After upgrading the app, make sure everything works before trying to switch to Hermes.
Each Hermes release is aimed at a specific RN version. The rule of thumb is to always follow Hermes releases strictly. Version mismatch can result in instant crash of your apps in the worst case scenario.
Edit your android/gradle.properties file and make sure hermesEnabled is true:
hermesEnabled=true
This property was added in React Native 0.71. If you can’t find it in your gradle.properties file, please refer to the documentation for the corresponding React Native version you're using.
Also, if you’re using ProGuard, you will need to add these rules in proguard-rules.pro :
-keep class com.facebook.hermes.unicode.** { *; }
-keep class com.facebook.jni.** { *; }
Next, if you’ve already built your app at least once, clean the build:
cd android && ./gradlew clean
That’s it! You should now be able to develop and deploy your app as usual:
npx react-native run-android
Since React Native 0.64, Hermes also runs on iOS. To enable Hermes for iOS, edit your ios/Podfile file and make the change illustrated below:
By default, you will be using Hermes if you’re on the New Architecture. By specifying a value such as true or false you can enable/disable Hermes as you wish. Like bellow 👇
Once you’ve configured it, you can install the Hermes pods with:
cd ios && pod install
That’s it! You should now be able to develop and deploy your app as usual:
npx react-native run-ios
You are all set 🚀
Static Hermes is the next version of Hermes, which has an extra feature that makes your app even faster and smaller.
Static Hermes can compile your JavaScript code into native code, which is the code that your device understands directly. This means that your app does not need to use Hermes or any other JavaScript engine to run, because it already has the native code inside it.
Static Hermes can do this only if you use TypeScript or Flow, which are tools that help you write better JavaScript code by checking the types of your variables and functions.
The main difference between Hermes and Static Hermes is that Hermes compiles your JavaScript code into bytecode at runtime, which means when your app starts running on your device. Static Hermes compiles your JavaScript code into native code at build time, which means when you create your app on your computer. This makes Static Hermes faster and smaller than Hermes, because it does not need to do any extra work at runtime.
Static Hermes was first introduced at React Native EU — 2023. It is still in experiment. I will write an in details article on Static Hermes 🙇♂️.
Now that you have successfully learned how to enable Hermes for both iOS and Android, you should know how to enable the New Architecture in both iOS and Android. This is because Hermes is a part of the New Architecture provided by the React Native team and Hermes cannot show its full power without enabling the New Architecture. So read the article below to enable the full New Architecture of your React Native app.
Article Link: React Native New Architecture (How to enable in new Android and IOS app)
Also, if you want to improve the code quality and optimize your React Native code, read this 👇
Article link: React Native app Performance Optimization: IOS & Android
Thank you for reading this article. I enjoy sharing my 5 years of experience in React-native, JavaScript, React & Node.js with you every day. If you enjoyed reading this article, I would appreciate it if you could follow me on Twitter & Medium.
If you find any ISSUE in this Guide BOOK, please create a PR to help the community 🔥