The docs (https://facebook.github.io/react-native/docs/hermes) do not mention anything about how to enable hermes for an existing native Android app which has RN integrated using a JS bundle.
The documentation has now been improved and published. Thanks!
@willholen I am still not sure how to enable Hermes for a hybrid Android app (native + RN). Even if I create a release JS bundle with Hermes enabled, the size of the RN .so libs that gets packaged in my native app is still roughly the same. How can I take advantage of the APK size reduction?
@prempalsingh Could you extract your APK and check which .so files are being bundled up?
In a release build you should have libhermes-executor-release.so and libhermes.so, and notably no libjsc.so or libhermes-executor-debug.so.
For reference, here is the part of the RN build responsible for excluding libraries based on project settings.
@prempalsingh there is multiple things if you want to do the hermes integration by yourself
build.gradle to exclude the libhermes-executor-debug.so or libhermes-executor-reslease.so or jscexecutor.so depends on which JS engine you are usingReactInstanceManagerBuilder.setJavaScriptExecutorFactory(new HermesExecutorFactory()); if you are using hermes./hermes -emit-binary -out outputfile inputfile -output-source-map
- about the app size, you may benefit from changing the JS engine from JSC to Hermes, but the binary jsbundle (hermes's output) is slightly bigger than the normal text bundle, then maybe you won't see the decreasing apk size
@tsengvn we universally see bytecode bundles up to 30% smaller than text bundles. I am surprised that in your case it is larger. I noticed that in your example command you are missing the optimization option "-O". Can you try it with that option?
@tmikov thanks a lot for pointing out my missing, i see the binary-bundle is smaller now
@tmikov I also noticed that the Hermes engine still work with the text bundle. Is this an expected behavior (to provide backward compatibility) ?
Yes, Hermes transparently recognizes both text and bytecode in most contexts. This makes it easier to adapt existing builds and pipelines since you can simply drop in a bytecode file without other code changes.
You should always make sure you're using bytecode in releases though, since it's significantly faster to both load and execute, and uses much less memory.
Thanks @tsengvn for mentioning the steps for doing hermes integration on my own. Everything works fine now. How can I modify the app build.gradle to include/exclude the correct libhermes-executor depending upon the build type?
I was able to exclude jsc by adding exclude "**/libjsc*.so" in my packagingOptions.
react.gradle should already be doing this, though if you've just modified your project settings you may need to ./gradlew clean once. See https://github.com/facebook/react-native/blob/b21a9419236175a1d7f93189a7aa33e143536f9a/react.gradle#L282
True but my project is setup in a different way. It is an Android app that depends on the packaged aar file of React Native. Another team works on the JS bundle which is downloaded in the app via an OTA update. The .so files are already packaged in the aar. Need to exclude them from getting packaged in my apk.
That snippet is intended to include the whole RN .aar with all the undesired .so files, and then delete some of them right before the APK is packaged.
Got it. My project doesn't include the react.gradle file so I copied the particular snippet and placed it in my build.gradle file. It still doesn't work.
I dug a little deeper and found that the .so files are never created in the transforms folder.
They are only created in build/intermediates/merged_native_libs and build/intermediates/stripped_native_libs. I guess this is why the snippet never works. Any idea why this might be happening?
EDIT : I think the task transformNativeLibsWithIntermediateJniLibsForDebug is responsible for creating the transformed .so files. This particular task does not exist for my app. 馃槙
I'm not sure why this would be. This is valuable feedback, and means we should bump the priority of the correct fix as described in the snippet comment. As a temporary workaround, you could try adjusting the path.
More info in case it helps -
Here are the last 4 tasks when I run the dry run for assembling my app's internal debug variant -

The transform task is missing.
I will try modifying the script to delete the .so files after the merge or strip task and let you know if that works.
Please do. Make sure to clean before each new attempt, since Gradle understandably doesn't realize that changes to build.gradle means changes to intermediate output directories.
I modified the script to delete the .so files from the stripped_native_libs folder before the packaging task. The files got deleted but my package task failed with a FileNotFoundException -

Looks like the package task still expects the deleted files to be there.
I came across a gradle plugin to exclude/include specific .so files. Using it also throws the same exception. 馃槙
Update for those facing a similar issue. I am using the following workaround -
def taskName = getGradle().getStartParameter().getTaskRequests().toString()
packagingOptions {
// For Hermes, delete all the libjsc* files
exclude "**/libjsc*.so"
if (taskName.contains("InternalDebug")) {
// Release libs take precedence and must be removed
// to allow debugging
exclude '**/libhermes-executor-release.so'
} else {
// Reduce size by deleting the debugger/inspector
exclude '**/libhermes-inspector.so'
exclude '**/libhermes-executor-debug.so'
}
}
Hope an official fix is released soon.
my issue currently using react-native in an integrated app: couldn't find DSO to load: libhermes.so
@tvelev92 This can happen if you exclude both libjsc and libhermes in an application. Can you inspect the APK and make sure that you include the JSVM you wanted to use?
@tvelev92 @willholen I am facing the same issue. But I am using jsc.
Error on Android is couldn't find DSO to load: libhermes.so, but mostly on rooted devices (94% rooted)
@ObidosDev cd android && ./gradlew clean will fix that error
Just created a PR to fix this: https://github.com/facebook/react-native/pull/30303
Most helpful comment
Update for those facing a similar issue. I am using the following workaround -
Hope an official fix is released soon.