chore: do not build Hermes from source (-25% build time) (#25035)#25046
chore: do not build Hermes from source (-25% build time) (#25035)#25046
Conversation
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->
## **Description**
We are patching only React Native Android source code so we don't need
to build also Hermes engine which is adding lot of build time. On my
machine it reduced build time by about 25% and I guess it could be even
more on CI.
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
AI agent: Use format `CHANGELOG entry: [fix/feat/chore]: [User-facing
description in past tense]`.
Examples: `fix: resolved token name display issue`, `feat: added dark
mode toggle`, `chore: updated dependencies`.
For non-user-facing changes, use `CHANGELOG entry: null`.
-->
CHANGELOG entry:
## **Related issues**
<!--
AI agent: Replace with `Fixes: #[ISSUE_NUMBER]` using the actual issue
number you're implementing.
-->
Fixes:
## **Manual testing steps**
<!--
AI agent: Write specific, contextual Gherkin steps based on what you
actually implemented.
Do NOT use generic placeholders like "my feature name". Be concrete
about the feature, scenario, and steps.
-->
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
<!--
AI agent: Check ALL boxes in this section (mark all as [x]).
-->
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
<!--
AI agent: Leave ALL boxes unchecked ([ ]) - these are for reviewers to
check, not the author.
-->
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Uses prebuilt Hermes to avoid compiling the engine from source,
reducing Android build time and setup complexity.
>
> - Patch React Native (`ReactAndroid/build.gradle.kts`) to depend on
`compileOnly("com.facebook.react:hermes-android:0.76.9")` and drop the
`hermes-engine` preBuild dependency
> - Remove `hermes-engine` includes/substitutions from RN
`settings.gradle.kts` and app `android/settings.gradle` (resolve Hermes
from Maven instead)
> - Update Yarn config: apply a new RN patch
(`.yarn/patches/react-native-patch-d76d50a92f.patch`) via `package.json`
and `yarn.lock`
> - Clean build script: delete ICU install step and its invocation in
`prebuild_android()`
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
096aebf. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #25046 +/- ##
==========================================
+ Coverage 79.96% 80.02% +0.06%
==========================================
Files 4257 4268 +11
Lines 109331 109875 +544
Branches 22889 23011 +122
==========================================
+ Hits 87429 87932 +503
- Misses 15835 15841 +6
- Partials 6067 6102 +35 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Previously there was production grade JS bundled (which is very slow) during Android debug builds but it's useless because JS is loaded from Metro for debug builds. **This affect only local debug builds.** **Cold cache debug build: 6m 57s -> 1m 15s 🚀 Hot cache debug build: 4m 29s -> 12s 🚀** _* Measured on my machine (with already included #25046 improvement)_ ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) AI agent: Use format `CHANGELOG entry: [fix/feat/chore]: [User-facing description in past tense]`. Examples: `fix: resolved token name display issue`, `feat: added dark mode toggle`, `chore: updated dependencies`. For non-user-facing changes, use `CHANGELOG entry: null`. --> CHANGELOG entry: ## **Related issues** <!-- AI agent: Replace with `Fixes: #[ISSUE_NUMBER]` using the actual issue number you're implementing. --> Fixes: ## **Manual testing steps** <!-- AI agent: Write specific, contextual Gherkin steps based on what you actually implemented. Do NOT use generic placeholders like "my feature name". Be concrete about the feature, scenario, and steps. --> ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- AI agent: Check ALL boxes in this section (mark all as [x]). --> - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** <!-- AI agent: Leave ALL boxes unchecked ([ ]) - these are for reviewers to check, not the author. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Optimizes Android debug build performance by avoiding JS/asset bundling for specific debug flavors. > > - Sets `react.debuggableVariants = ["qaDebug", "prodDebug", "flaskDebug"]` in `android/app/build.gradle` to skip bundle generation for these debuggable variants during builds > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 94ad613. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Credit: @Nodonisko Previously there was production grade JS bundled (which is very slow) during Android debug builds but it's useless because JS is loaded from Metro for debug builds. **This affect only local debug builds.** **Cold cache debug build: 6m 57s -> 1m 15s 🚀 Hot cache debug build: 4m 29s -> 12s 🚀** _* Measured on my machine (with already included #25046 improvement)_ ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) AI agent: Use format `CHANGELOG entry: [fix/feat/chore]: [User-facing description in past tense]`. Examples: `fix: resolved token name display issue`, `feat: added dark mode toggle`, `chore: updated dependencies`. For non-user-facing changes, use `CHANGELOG entry: null`. --> CHANGELOG entry: null ## **Related issues** <!-- AI agent: Replace with `Fixes: #[ISSUE_NUMBER]` using the actual issue number you're implementing. --> Fixes: ## **Manual testing steps** <!-- AI agent: Write specific, contextual Gherkin steps based on what you actually implemented. Do NOT use generic placeholders like "my feature name". Be concrete about the feature, scenario, and steps. --> ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- AI agent: Check ALL boxes in this section (mark all as [x]). --> - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** <!-- AI agent: Leave ALL boxes unchecked ([ ]) - these are for reviewers to check, not the author. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk build-time change limited to local Android debug variants; main risk is misclassifying a variant as debuggable and skipping bundling where it’s needed. > > **Overview** > Configures React Native Gradle to treat `qaDebug`, `prodDebug`, and `flaskDebug` as *debuggable variants*, so Gradle skips JS bundle/assets bundling for these builds (reducing local debug build time). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 35d5ca6. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. Co-authored-by: Daniel Suchý <suchydan@gmail.com>
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
This is a high-risk change because:
Since this modifies the fundamental JavaScript execution layer, all E2E tests should run to validate that the app functions correctly with the prebuilt Hermes engine. A comprehensive test run will help catch any potential regressions in JavaScript execution, performance, or compatibility. Performance Test Selection: |
|



Description
We are patching only React Native Android source code so we don't need to build also Hermes engine which is adding lot of build time. On my machine it reduced build time by about 25% and I guess it could be even more on CI.
Changelog
CHANGELOG entry: null
Related issues
Fixes:
Manual testing steps
Screenshots/Recordings
Before
After
Pre-merge author checklist
Standards.
Pre-merge reviewer checklist
Note
Medium Risk
Build configuration now pulls
com.facebook.react:hermes-android:0.76.9from Maven and removes the localhermes-engineproject, which could break Android builds if dependency substitution/version alignment is off. Runtime app behavior shouldn’t change, but CI/build tooling is impacted.Overview
Switches Android builds to use prebuilt Hermes from Maven Central instead of compiling Hermes from the React Native source tree, via a new Yarn patch (
.yarn/patches/react-native-patch-d76d50a92f.patch) that removes thehermes-engineGradle project wiring and replaces it withcompileOnly("com.facebook.react:hermes-android:0.76.9").Updates
android/settings.gradledependency substitution to no longer substitutehermes-android/hermes-engineto local projects, adjusts thereact-nativepatched dependency entry inpackage.json/yarn.lock, and removes the Android build script step that installed ICU libraries for Hermes compilation.Written by Cursor Bugbot for commit 0636dd2. This will update automatically on new commits. Configure here.
Description
Changelog
CHANGELOG entry:
Related issues
Fixes:
Manual testing steps
Screenshots/Recordings
Before
After
Pre-merge author checklist
Pre-merge reviewer checklist