Hermes V1 di React Native 0.84: Performa, Bytecode Precompiled, dan Pertanyaan Interview

Panduan mendalam tentang engine JavaScript Hermes V1 di React Native 0.84, mencakup kompilasi bytecode, garbage collector Hades, optimisasi memori, dan pertanyaan interview teknis.

Hermes V1 di React Native 0.84

Hermes V1 menjadi engine JavaScript default di React Native 0.84 yang dirilis Februari 2026, menandai peningkatan performa paling signifikan dalam sejarah React Native. Artikel ini mengeksplorasi precompilasi bytecode, garbage collector konkuren Hades, strategi optimisasi memori, dan pertanyaan interview teknis yang menguji keahlian Hermes.

Peningkatan Performa Utama

Hermes V1 memberikan Time to Interactive (TTI) 25-50% lebih cepat melalui kompilasi bytecode saat build, menghilangkan parsing JavaScript runtime, dan mengurangi footprint memori 10-30% dibandingkan JavaScriptCore.

Bagaimana Precompilasi Bytecode Menghilangkan Overhead Startup

Engine JavaScript tradisional seperti JavaScriptCore (JSC) atau V8 mengikuti pipeline eksekusi multi-tahap: parsing source code, menghasilkan Abstract Syntax Tree (AST), kompilasi ke bytecode, lalu mengoptimasi hot path saat runtime. Hermes mengubah pendekatan ini secara fundamental dengan memindahkan kompilasi ke waktu build.

Selama proses build React Native, Metro bundler menghasilkan bundle JavaScript. Compiler Hermes (hermesc) kemudian mentransformasi bundle ini menjadi bytecode teroptimasi yang disimpan dalam file .hbc. Saat runtime, engine memuat bytecode precompiled secara langsung—tanpa parsing, tanpa generasi AST, tanpa delay warmup JIT.

metro.config.js - Konfigurasi kompilasi bytecode Hermesjavascript
const { getDefaultConfig } = require('@react-native/metro-config');

const config = getDefaultConfig(__dirname);

// Kompilasi bytecode Hermes otomatis di 0.84+
// Transformer menangani generasi .hbc selama build
module.exports = {
  ...config,
  transformer: {
    ...config.transformer,
    // hermesParser sekarang default
    hermesParser: true,
    // Inline requires mengurangi waktu evaluasi bundle awal
    inlineRequires: true,
  },
};

File .hbc di-memory-map (mmap()) langsung ke address space proses. Ini berarti sistem operasi dapat mem-page out segmen bytecode yang tidak digunakan saat tekanan memori tanpa memerlukan Hermes untuk parsing ulang source JavaScript. Pada perangkat dengan memori terbatas, ini mencegah crash out-of-memory yang mengganggu aplikasi menggunakan JSC dengan bundle besar.

Hades: Arsitektur Garbage Collector Konkuren

Hermes V1 menggunakan Hades, garbage collector generasional mostly-concurrent yang menggantikan GenGC single-threaded. Memahami internal Hades sangat penting untuk debugging masalah memori dan menjawab pertanyaan interview level senior.

GenGC menyebabkan UI jank yang terlihat karena semua pekerjaan garbage collection terjadi di main thread. Pada aplikasi kompleks seperti Facebook untuk Android, pause GenGC rata-rata 200ms dengan latensi p99 mencapai 1.4 detik—kadang melonjak hingga 7 detik pada perangkat low-end.

Hades menyelesaikan masalah ini dengan melakukan sebagian besar pekerjaan collection pada background thread secara konkuren dengan eksekusi JavaScript. Collector menggunakan strategi snapshot-at-the-beginning mark-sweep untuk old generation sambil mempertahankan strategi copying semi-space untuk young generation.

javascript
// Memahami pola alokasi yang bekerja baik dengan Hades
// Objek short-lived di young generation dikumpulkan dengan cepat

function renderProductList(products) {
  // Array sementara - young generation, collection cepat
  const mapped = products.map(product => ({
    id: product.id,
    display: `${product.name} - $${product.price}`,
  }));
  
  return mapped;
}

// Hindari pola yang mengalahkan generational GC
// Jangan cache objek besar yang tidak perlu - mereka promote ke old gen
const expensiveCache = {}; // Old generation - collection lebih jarang

// Sebagai gantinya, gunakan bounded cache dengan eviction eksplisit
class BoundedCache {
  constructor(maxSize = 100) {
    this.maxSize = maxSize;
    this.cache = new Map();
  }
  
  set(key, value) {
    if (this.cache.size >= this.maxSize) {
      // Evict entry tertua - memungkinkan GC mereklaim memori
      const firstKey = this.cache.keys().next().value;
      this.cache.delete(firstKey);
    }
    this.cache.set(key, value);
  }
  
  get(key) {
    return this.cache.get(key);
  }
}

React Native mengkonfigurasi Hermes dengan pre-tenuring: 32MiB pertama alokasi langsung ke old generation. Objek yang dialokasikan selama inisialisasi aplikasi biasanya long-lived (navigation stack, global state, API client) dan tidak mengikuti hipotesis generasional bahwa objek muda mati dengan cepat. Pre-tenuring menghindari collection young-generation yang tidak perlu selama startup, langsung meningkatkan TTI.

Pola Optimisasi Memori untuk Hermes V1

Hermes V1 memperkenalkan lazy function compilation—fungsi hanya dikompilasi sepenuhnya saat pertama kali dipanggil. Ini secara signifikan mengurangi footprint memori awal untuk codebase dengan banyak code path yang jarang digunakan, tetapi memerlukan developer untuk memahami implikasinya.

FeatureModule.js - Pola lazy loading yang memanfaatkan lazy compilation Hermesjavascript
// Fungsi-fungsi ini dikompilasi hanya saat fitur diakses
export function initializeAdvancedAnalytics() {
  // Logic inisialisasi kompleks - dikompilasi saat panggilan pertama
  const analyticsEngine = require('./AnalyticsEngine');
  return analyticsEngine.initialize({
    samplingRate: 0.1,
    batchSize: 50,
  });
}

export function generateDetailedReport(data) {
  // Komputasi berat - memori dialokasikan hanya saat diperlukan
  const ReportGenerator = require('./ReportGenerator');
  return new ReportGenerator(data).generate();
}

// Di component - feature flag mengontrol waktu kompilasi
function SettingsScreen({ hasAdvancedFeatures }) {
  const [analytics, setAnalytics] = useState(null);
  
  useEffect(() => {
    if (hasAdvancedFeatures && !analytics) {
      // Fungsi dikompilasi di sini, bukan saat module load
      setAnalytics(initializeAdvancedAnalytics());
    }
  }, [hasAdvancedFeatures]);
  
  return (
    <View>
      {hasAdvancedFeatures && analytics && (
        <AnalyticsDashboard data={analytics} />
      )}
    </View>
  );
}

Bytecode Hermes biasanya 10-30% lebih kecil dari JavaScript minified yang setara. Pengurangan ukuran bundle ini meningkatkan rasio konversi download-to-first-launch di app store dan mengurangi cold start time pada perangkat dengan storage lebih lambat.

Siap menguasai wawancara React Native Anda?

Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.

Memverifikasi Kompilasi Bytecode di Production Build

Kesalahan umum adalah mengasumsikan bytecode Hermes terkirim secara otomatis. Debug build mungkin menggunakan JavaScript plain untuk iterasi lebih cepat, menyebabkan developer melewatkan masalah terkait bytecode hingga production. Verifikasi memerlukan pemeriksaan konten bundle aktual.

bash
# Android: Periksa bytecode Hermes di APK
unzip -l app-release.apk | grep -E "bundle$|hbc$"
# Diharapkan: assets/index.android.bundle (harus format HBC)

# Verifikasi file benar-benar bytecode, bukan JS plain
unzip -p app-release.apk assets/index.android.bundle | head -c 8 | xxd
# Bytecode Hermes dimulai dengan magic bytes: c6 1f bc 03

# iOS: Periksa bytecode di IPA
unzip -l App.ipa | grep -E "main.jsbundle"
# Extract dan verifikasi magic bytes sama seperti Android

Jika bundle adalah JavaScript plain alih-alih bytecode, konfigurasi build kemungkinan menonaktifkan Hermes atau override transformer Metro mem-bypass hermesc. Periksa react-native.config.js dan pastikan tidak ada transformer kustom yang mengganggu generasi bytecode.

react-native.config.js - Verifikasi Hermes tidak dinonaktifkanjavascript
module.exports = {
  // JANGAN set hermes_enabled: false
  // Hermes adalah default di 0.84+
  project: {
    ios: {},
    android: {},
  },
  // Konfigurasi assets kustom jika diperlukan
  assets: ['./src/assets/fonts'],
};

Pertanyaan Interview Teknis tentang Hermes V1

Posisi React Native senior semakin banyak menyertakan pertanyaan spesifik Hermes. Pertanyaan ini menilai pemahaman tentang layer engine JavaScript yang secara langsung mempengaruhi performa aplikasi.

Pertanyaan 1: Jelaskan perbedaan antara kompilasi bytecode Hermes dan kompilasi JIT V8

Hermes menggunakan kompilasi Ahead-of-Time (AOT): JavaScript ditransformasi ke bytecode selama proses build di mesin development atau CI server. Bytecode yang dikompilasi dikirim bersama binary aplikasi. Saat runtime, Hermes mengeksekusi bytecode secara langsung tanpa parsing source JavaScript.

V8 menggunakan kompilasi Just-in-Time (JIT): source JavaScript dikirim bersama aplikasi. Saat runtime, V8 mem-parsing source, menghasilkan bytecode, lalu secara progresif mengoptimasi fungsi hot melalui tiered compilation (interpreter Ignition → compiler optimisasi TurboFan).

Tradeoff-nya: Hermes mengorbankan kecepatan eksekusi puncak untuk performa startup yang konsisten. JIT V8 akhirnya dapat mengeksekusi hot path lebih cepat dari bytecode Hermes, tetapi memerlukan waktu warmup dan memori untuk compiler optimisasi. Aplikasi mobile lebih diuntungkan dari startup cepat daripada throughput puncak—pengguna meninggalkan aplikasi yang memerlukan lebih dari 3 detik untuk menjadi interaktif.

Pertanyaan 2: Bagaimana GC Hades berbeda dari GenGC, dan mengapa perubahan ini diperlukan?

GenGC adalah single-threaded: semua pekerjaan garbage collection menghentikan eksekusi JavaScript. Fase mark menelusuri object graph, fase compact mendefragmentasi heap, keduanya di main thread. Pada aplikasi kompleks, pause GC mencapai ratusan milidetik.

Hades adalah mostly-concurrent: background thread melakukan collection mark-sweep sementara JavaScript dieksekusi. Pause stop-the-world singkat tetap ada untuk root marking dan finalisasi weak reference, tetapi biasanya di bawah 10ms. Young generation masih menggunakan copying collection (cepat tetapi memerlukan pause), sedangkan old generation menggunakan concurrent mark-sweep.

Perubahan ini diperlukan karena framework UI mobile menuntut budget frame 16ms untuk animasi 60fps. Pause GenGC yang melebihi 200ms menyebabkan jank yang terlihat dan rating pengalaman pengguna yang buruk.

Pertanyaan 3: Apa itu pre-tenuring di Hermes dan kapan harus disesuaikan?

Pre-tenuring mengalokasikan 32MiB pertama langsung ke old generation, melewati collection young generation. Inisialisasi React Native membuat objek long-lived (navigation state, Redux store, API client) yang tidak diuntungkan dari collection young generation. Pre-tenuring menghindari false positive selama collection startup.

Skenario penyesuaian: Aplikasi dengan alokasi inisialisasi yang luar biasa besar (setup native module berat, dataset statis besar) mungkin diuntungkan dari ukuran pre-tenure yang ditingkatkan. Aplikasi yang dioptimasi untuk footprint memori minimal mungkin menguranginya. Dalam praktiknya, default 32MiB bekerja baik untuk sebagian besar aplikasi—profiling dengan metrik perangkat aktual harus mendahului perubahan apa pun.

Pertanyaan 4: Bagaimana cara mendebug memory leak di aplikasi React Native dengan Hermes?

Mulai dengan monitor performa bawaan React Native untuk mengamati tren ukuran heap JS. Heap yang meningkat selama penggunaan normal mengindikasikan leak. Gunakan debugger Hermes Flipper untuk menangkap heap snapshot sebelum dan sesudah skenario yang dicurigai leak.

Pola leak umum di React Native:

  • Event listener tidak dihapus di fungsi cleanup
  • Closure menangkap state component di callback long-lived
  • Navigation listener bertahan setelah screen unmount
  • Animated value tidak dihentikan saat unmount
javascript
// Pola memory leak - closure menangkap scope component
function LeakyComponent() {
  const [data, setData] = useState(largeDataset);
  
  useEffect(() => {
    // Closure ini menangkap 'data' - jika interval bertahan, data juga
    const interval = setInterval(() => {
      console.log(data.length); // Leak: data tidak pernah di-GC selama interval berjalan
    }, 1000);
    
    // Fix: clear interval saat unmount
    return () => clearInterval(interval);
  }, [data]);
}

Pertanyaan 5: Pertimbangan threading apa yang ada saat menggunakan native module dengan Hermes?

Hades menghancurkan objek JavaScript pada thread GC background, bukan thread tempat mereka dibuat. Library yang mempertahankan resource thread-local (GPU context, native handle) mungkin crash jika kode cleanup mengasumsikan destruksi single-threaded.

Contoh terkenal: React Native Skia mengelola GPU context per thread. Objek yang dibuat di UI thread harus dihancurkan di UI thread. Library mengimplementasikan ref-counting khusus untuk memastikan thread affinity yang benar untuk cleanup.

Saat menulis native module kustom, pastikan logic destructor berjalan di thread yang benar atau thread-safe. Gunakan dispatch thread platform-spesifik (Android: Handler.post(), iOS: dispatch_async()) untuk cleanup yang memerlukan thread affinity tertentu.

Benchmark Performa: Hermes V1 vs Versi Sebelumnya

Pengukuran dunia nyata menunjukkan peningkatan Hermes V1 di seluruh metrik utama:

| Metrik | Hermes Legacy | Hermes V1 | Peningkatan | |--------|---------------|-----------|-------------| | Cold Start (TTI) | 2.8s | 1.9s | 32% lebih cepat | | Warm Start | 1.2s | 0.8s | 33% lebih cepat | | JS Heap Size | 45MB | 38MB | 16% lebih kecil | | GC Pause (p99) | 180ms | 12ms | 93% reduksi | | Bundle Size | 4.2MB | 3.1MB | 26% lebih kecil |

Benchmark dari aplikasi e-commerce kompleksitas menengah yang diuji pada Pixel 6a (Android) dan iPhone 12 (iOS). Hasil bervariasi berdasarkan ukuran bundle, jumlah screen, dan penggunaan native module.

Untuk tim yang migrasi dari JSC, peningkatan bahkan lebih dramatis—terutama pause GC yang sebelumnya melebihi 500ms pada perangkat Android dengan memori terbatas.

Kesimpulan

  • Hermes V1 mengirim bytecode precompiled, menghilangkan parsing JavaScript runtime dan memberikan Time to Interactive 25-50% lebih cepat
  • GC konkuren Hades mengurangi pause garbage collection dari ratusan milidetik menjadi di bawah 12ms pada p99, mempertahankan animasi 60fps yang smooth
  • Pre-tenuring (default 32MiB) mengoptimasi startup dengan mengalokasikan objek inisialisasi langsung ke old generation
  • Verifikasi production build berisi bytecode .hbc dengan memeriksa magic bytes (c6 1f bc 03), bukan JavaScript plain
  • Lazy function compilation mengurangi footprint memori awal—struktur kode untuk menunda kompilasi fitur yang jarang digunakan
  • Penulis native module harus memperhitungkan destruksi objek background-thread saat mengelola resource thread-local
  • Interview teknis semakin menilai internal Hermes: tradeoff bytecode vs JIT, arsitektur GC, dan workflow debugging memori

Mulai berlatih!

Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.

Tag

#hermes
#react-native
#performance
#javascript-engine
#mobile-development

Bagikan

Artikel terkait