Hermes — to silnik JavaScript o otwartym kodzie źródłowym, opracowany specjalnie dla React Native i zoptymalizowany pod kątem urządzeń mobilnych. W przeciwieństwie do JavaScriptCore, Hermes wstępnie kompiluje kod JS do kodu bajtowego na etapie budowania, zapewniając szybki start aplikacji. Według Meta, Hermes Docs, 2024, Hermes jest domyślnie używany w React Native od wersji 0.70.
Najważniejsze
Hermes — to kompaktowy silnik JavaScript, stworzony przez zespół Meta specjalnie dla React Native. Został ogłoszony w 2019 roku jako alternatywa dla JavaScriptCore (JSC), który był domyślnie używany w React Native. Głównym celem Hermes jest zapewnienie jak najszybszego uruchamiania aplikacji na urządzeniach mobilnych, szczególnie na Androidzie z ograniczonymi zasobami.
Kluczową cechą Hermes jest wstępna kompilacja (AOT — Ahead-of-Time). W przeciwieństwie do tradycyjnych silników JS, które kompilują kod w czasie wykonania (JIT — Just-in-Time), Hermes kompiluje JavaScript do kodu bajtowego już na etapie budowania aplikacji. Oznacza to, że na urządzeniu nie odbywa się kompilacja — kod bajtowy jest natychmiast wykonywany przez maszynę wirtualną Hermes.
Hermes nie jest uniwersalnym silnikiem JS — jest zoptymalizowany wyłącznie dla scenariuszy React Native. Brak w nim funkcji niepotrzebnych w programowaniu mobilnym: eval, generatorów, niektórych funkcji ES6. Pozwala to uczynić silnik bardziej kompaktowym i szybszym. Według Meta, rozmiar Hermes wynosi około 200–300 KB w postaci skompresowanej, co jest znacznie mniejsze niż JSC (około 2–3 MB).
Architektura Hermes różni się od tradycyjnych silników JS brakiem kompilatora JIT. Zamiast tego Hermes używa wydajnej maszyny wirtualnej (VM), która wykonuje wstępnie skompilowany kod bajtowy. Rezygnacja z JIT daje trzy kluczowe zalety: przewidywalną wydajność, mniejsze zużycie pamięci i skrócenie czasu uruchamiania.
Kod bajtowy Hermes to kompaktowa reprezentacja kodu JavaScript, zoptymalizowana pod kątem szybkiego wykonywania. Na etapie budowania (przez Metro) pliki JavaScript są kompilowane do plików .hbc (Hermes Bytecode). Aplikacja ładuje te pliki, a VM Hermes wykonuje je bez dodatkowej kompilacji. Proces budowania jest zintegrowany z Metro poprzez wtyczkę hermes-transformer.
Proces przetwarzania JavaScript w Hermes składa się z trzech etapów: Parse — analiza składniowa kodu źródłowego, Compile — translacja do kodu bajtowego, Execute — wykonanie kodu bajtowego przez maszynę wirtualną. Pierwsze dwa etapy są wykonywane na etapie budowania, trzeci — na urządzeniu. Zasadniczo różni się to od JSC, gdzie wszystkie trzy etapy są wykonywane na urządzeniu.
# Kompilacja kodu bajtowego Hermes podczas budowania
hermes -emit-binary -out index.hbc index.js
# Sprawdź rozmiar wygenerowanego kodu bajtowego
ls -lh index.hbc
# Wyświetl statystyki kodu bajtowego
hermes -dump-bytecode index.hbc
# Optymalizuj kod bajtowy dla produkcji
hermes -O index.js -emit-binary -O target.hbc
Po kompilacji wszystkie pliki .hbc są pakowane do APK lub IPA wraz z kodem natywnym. Przy uruchomieniu aplikacji VM Hermes ładuje kod bajtowy i zaczyna wykonywanie praktycznie natychmiast — nie wymaga czasu na rozgrzanie JIT, typowego dla V8 i JSC.
Porównanie Hermes i JavaScriptCore (JSC) pomaga zrozumieć, kiedy który silnik wybrać. JSC — pełnoprawny silnik JS od Apple, używany w Safari. Hermes — specjalistyczny silnik dla React Native. Wybór między nimi zależy od priorytetów projektu.
| Charakterystyka | Hermes | JavaScriptCore |
|---|---|---|
| Kompilacja | AOT (na etapie budowania) | JIT (na urządzeniu) |
| Czas uruchamiania | 50–100 ms | 200–400 ms |
| Zużycie pamięci | 30–40% mniej | Poziom bazowy |
| Rozmiar | ~250 KB (skompresowany) | ~2 MB (skompresowany) |
| Wsparcie ES6+ | Ograniczone | Pełne |
Hermes wygrywa w szybkości uruchamiania i zużyciu pamięci, ale ustępuje JSC w wydajności wykonywania złożonych obliczeń. Kompilacja JIT JSC optymalizuje gorące fragmenty kodu podczas wykonywania, co daje przewagę w operacjach intensywnie wykorzystujących CPU. W typowej aplikacji React Native, gdzie aktualizacje UI i nawigacja stanowią główne obciążenie, Hermes zapewnia lepsze doświadczenie użytkownika dzięki szybkiemu uruchamianiu.
Hermes zawiera kilka optymalizacji specyficznych dla React Native. Główną z nich jest integracja z JSI (JavaScript Interface). Hermes natywnie obsługuje JSI, co pozwala na używanie nowej architektury React Native (Fabric + Turbo Module) bez dodatkowych warstw. To czyni Hermes i nową architekturę idealną parą dla maksymalnej wydajności.
Hermes używa garbage collectora z strategią pokoleniową (generational GC), zoptymalizowaną dla urządzeń mobilnych. W przeciwieństwie do JSC, gdzie garbage collection może powodować zauważalne pauzy w UI (jank), Hermes wykonuje GC małymi porcjami między klatkami, minimalizując wpływ na doświadczenie użytkownika. Według Meta, pauzy GC w Hermes są 2–3 razy krótsze niż w JSC w typowych scenariuszach React Native.
Hermes obsługuje leniwe ładowanie modułów — moduł JavaScript jest kompilowany tylko wtedy, gdy jest rzeczywiście potrzebny. To zmniejsza rozmiar kodu bajtowego i przyspiesza uruchamianie. Dodatkowo Hermes oblicza wyrażenia stałe na etapie kompilacji, zastępując wywołania funkcji wartościami stałymi tam, gdzie to możliwe.
// Przykład optymalizacji specyficznych dla Hermes
// 1. Hermes wstawia wyrażenia stałe
const TAX_RATE = 0.07;
const price = 100;
// Hermes wstępnie oblicza: TAX_RATE * price podczas kompilacji
const totalWithTax = price * (1 + TAX_RATE);
// 2. Hermes optymalizuje łańcuchy dostępu do właściwości
const config = { api: { timeout: 5000 } };
// Hermes wewnętrznie buforuje dostęp do config.api
const timeout = config.api.timeout;
fetch(url, { timeout });
Warto zaznaczyć, że Hermes obsługuje debugowanie przez Chrome DevTools (od wersji Hermes 0.12). Deweloper może używać znanych narzędzi: breakpointy, profilowanie pamięci, inspekcja zmiennych. Eliminuje to jeden z głównych zarzutów wobec Hermes we wczesnych wersjach, gdy debugowanie było ograniczone.
Konfiguracja Hermes zależy od wersji React Native. Od React Native 0.70 Hermes jest domyślnie włączony dla nowych projektów. Dla projektów utworzonych wcześniej lub przy potrzebie przełączania między silnikami, konfiguracja odbywa się poprzez ustawienia budowania.
Dla Androida Hermes włącza się w pliku android/app/build.gradle poprzez flagę hermesEnabled. Dla iOS konfiguracja odbywa się w Podfile poprzez zmienną :hermes_enabled. Po zmianie konfiguracji należy ponownie zainstalować pody i przebudować projekt.
// android/app/build.gradle — włącz Hermes
project.ext.react = [
enableHermes: true
]
// iOS Podfile — włącz Hermes
hermes_enabled = true
pod 'hermes-engine'
Aby sprawdzić, czy Hermes jest używany w aplikacji, wykonaj adb logcat | grep Hermes na Androidzie lub sprawdź konsolę Xcode na iOS. Przy uruchomieniu aplikacji Hermes wyświetla komunikat „Hermes VM initialized” lub podobny. Można również wykonać globalThis.HermesInternal w kodzie JavaScript — jeśli Hermes jest aktywny, ta właściwość będzie dostępna.
// Sprawdź, czy Hermes jest uruchomiony
if (typeof globalThis.HermesInternal !== 'undefined') {
console.log('✅ Silnik Hermes aktywny');
console.log(
'Wersja:',
globalThis.HermesInternal.getEngineProperties()
);
} else {
console.log('❌ Hermes nieaktywny (przejście na JSC)');
}
Często zadawane pytania
Tak, Hermes jest w pełni kompatybilny z nową architekturą React Native (Fabric + Turbo Module). Co więcej, Hermes i JSI były opracowywane razem i zapewniają najlepszą wydajność w parze.
Tak, Hermes obsługuje obie platformy — iOS i Android. Na iOS Hermes zastępuje standardowy JavaScriptCore, zapewniając te same zalety: szybkie uruchamianie i mniejsze zużycie pamięci.
Hermes obsługuje większość funkcji ES6+, ale z ograniczeniami: brak eval, generatorów i Proxy. Zaleca się używanie transpilacji Babel dla kompatybilności, podobnie jak w zwykłym React Native.
Hermes zmniejsza rozmiar aplikacji dzięki kompaktowemu kodowi bajtowemu i mniejszemu rozmiarowi samego silnika. Kod bajtowy jest zazwyczaj o 20–30% bardziej kompaktowy niż odpowiadający mu kod JS, a sam silnik waży ~250 KB w porównaniu do ~2 MB w JSC.
Większość bibliotek jest kompatybilna z Hermes. Jeśli biblioteka używa eval, Proxy lub niestandardowych funkcji — sprawdź, czy ma wersję kompatybilną z Hermes. Można również użyć wtyczek Babel do zastąpienia nieobsługiwanych konstrukcji.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również