Technical Guide, Part 2: Integrating Hermes with React Native

Mike Grabowski
Aug 16 · 7 min read
Technical guide, part 2: integrating Hermes with React Native

The latest React Native 0.64 release adds support for the Hermes engine on iOS, and this is a direct result of our intensive work with teams at Facebook and Microsoft. We share the journey to Hermes on iOS in a series of four pieces:

While the first two introduce Hermes and give details about running Hermes in production, the last two offer solid technical insights based on the implementation done. They’re actually one two-part guide.

If you prefer to dig the code yourself, here’s my PR to React Native. Otherwise, fasten your seatbelts and you’re in for another technical ride!

Integrating Hermes with React Native

Thankfully, @alloy and Microsoft team were here before as well! Their work on enabling Hermes in their macOS fork not only made it easier to compile Hermes for iOS, as discussed in the first part of the guide, but also made it easier to integrate Hermes with React Native.

By upstreaming some of their work from their fork, they paved the way for the integration and definitely made my life much easier!

For more context, you may want to check this PR to React Native macOS that captures the entire work that @alloy did to bring Hermes to Apple computers.

Integrating Hermes with React Native
Integrating Hermes with React Native

Where to start the integration process

Executing JavaScript code
Executing JavaScript code

As of today, there are two JSExecutors available inside React Native. First one, which you may be most familiar with, is a JSCExecutor that executes your JavaScript code with the JavaScript Core engine. The other one uses Hermes and is called HermesExecutor. React Native creates an instance of an executor via an ExecutorFactory.

You’re probably wondering why we have two executors available within React Native if, at least at the time of writing this step-by-step technical guide, there was only JavaScript Core available as the engine on iOS.

The answer is simple — the majority of the core React Native code is written in C++. That makes it easier to share core between Android and iOS, when possible. To answer the question from the previous paragraph, JSCExecutorFactory is a factory written in C++ that is shared between iOS and Android. HermesExecutorFactory is a factory written in C++ that is exclusive to Android, and located inside the ReactAndroid folder as a result.

When to use Hermes over JSC

In other words, moving HermesExecutor outside of ReactAndroid folder to a shared folder and including it in both iOS and Android builds was already part of the success. This is exactly what happened in this PR.

Once this was done, the next step was to activate that mechanism — teach React Native when to use Hermes over JSC. Our approach was to make it as smooth as possible by reducing the amount of steps to be done by the developer to a bare minimum. I am proud to say we have managed to reduce it to exactly one step. And that’s what I have described in the next step.

How to activate the engine

In order to turn on Hermes on iOS, all you have to do is just one step — set hermes_enabled to true where you have your use_react_native function:

Turning on Hermes on iOS
Turning on Hermes on iOS

Then run the pod install command once again. This will install any new native dependencies you have added, and reconfigure the project with the latest settings in mind. In this particular example, it will add the Hermes framework to your project.

Note: If you’re interested in how Hermes framework is generated and what lies inside, please check the previous part of this guide, where we go through the same process of generating Hermes framework step by step.

Unlike any other native code you may have worked with, there is no npm install or yarn install to do. This is because Hermes is already included with every React Native release and there is no need to install any additional packages to set things up.

Since the presence of Hermes binaries dictates whether it should or should not be used (based on your preferred setting in a Podfile), we can rely on this in all other places where we need to choose the right engine:

Choosing the right engine
Choosing the right engine

This macro will set a project-wide variable RCT_USE_HERMES if, and only if, Hermes headers are included in the project. As we know from the previous paragraph, such scenario will be true in cases when users opted-in to use Hermes.

Based on this behavior, we can now choose either Hermes or JSC executor (as mentioned at the beginning of this guide), depending on the presence of RCT_USE_HERMES.

First of all, we can choose which file to import in our file:

Activating Hermes
Activating Hermes

and then initialize the proper executor factory:

Activating Hermes
Activating Hermes

Thanks to that mechanism, RCTCxxBridge can choose the right executor factory, depending on whether Hermes is available or not. Thanks to the pre-existing abstraction within React Native that separates the engine from the rest of the architecture, no further changes were required in order to actually switch the engine itself.

How it works in practice

This is because the <NewAppScreen> is a cross-platform component and is actually running on Android too; Hermes has been out there in production for quite some time. That’s just another benefit of a cross-platform architecture.

The same thing applies to other pieces such as Flipper. I could go into details on how it works and what are its greatest benefits, but I guess there has to be something I leave for you to explore further!

Try Hermes yourself

Can’t wait to see what you build with Hermes and how it turns out for you in production! While we continue our benchmarking, please share your findings and feelings on Twitter — make sure to tag me so that we can celebrate together!

Find out more

This article was originally published at callstack.com on June 14, 2021.

Callstack Engineers

We are React Native community-trusted, extremely skilled…

Callstack Engineers

We are React Native community-trusted, extremely skilled Javascript developers ready for hire for your next React Native and React project, now.

Mike Grabowski

Written by

CTO at Callstack.com, React Native developer. Dealing with timezone differences between Europe and USA. Writing with ❤ from Poland.

Callstack Engineers

We are React Native community-trusted, extremely skilled Javascript developers ready for hire for your next React Native and React project, now.