Episode optimisasi: mengurangi overhead startup dengan prepackaging bytecode di build time, memakai flag optimizer -O dan -output-source-map untuk bytecode yang lebih kecil dan cepat, serta menganalisis bagaimana ukuran bundle memengaruhi cold start di perangkat nyata.

Di episode 4 kita tahu artifact build Hermes adalah bytecode .hbc. Sekarang pertanyaannya: bagaimana membuat bytecode itu secepat dan sekecil mungkin, sehingga cold start terasa instan?
Episode 5 membahas tiga hal: prepackaging bytecode, optimizer -O, dan pengaruh ukuran bundle terhadap startup. Ini episode favorit bagi siapa saja yang peduli metrik.
Saat user membuka app, urutan yang terjadi adalah: load APK, inisialisasi runtime, load bundle, dan eksekusi kode pertama. Di engine dengan JIT, ada dua pekerjaan ekstra: mengurai JavaScript dan memanaskan JIT. Hermes menghilangkan keduanya dengan mengirim bytecode yang sudah jadi.
Tapi bytecode tidak otomatis optimal. Ukuran file memengaruhi waktu load dari disk, dan alokasi object saat eksekusi pertama memengaruhi persepsi user. Optimisasi di build time adalah investasi yang terbayar di setiap peluncuran.
Prepackaging berarti seluruh kerja kompilasi dipindahkan ke build time, sehingga perangkat tidak melakukan apa pun kecuali mengeksekusi. Di React Native ini sudah terjadi otomatis: bundle dikompilasi hermesc sebelum di-embedd ke APK. Kita bisa memastikan dengan memeriksa bahwa asset yang ter-embedd berformat bytecode:
cd android
./gradlew assembleRelease
unzip -l app/build/outputs/apk/release/app-release.apk \
| grep -i bundleJika baris yang muncul berakhiran .hbc, prepackaging berjalan benar. Konsekuensi positifnya: tidak ada parsing di device, tidak ada JIT warmup, dan bundle bisa ditandatangani — memori dan CPU hanya dipakai untuk eksekusi murni.
Info
Saat --dev true, React Native melewati prepackaging dan memuat bundle JS langsung dari Metro — startup akan lebih lambat dan memori lebih besar. Pengukuran performa yang sah selalu memakai build release.
Selain prepackaging, Hermes menerapkan lazy compilation (kita singgung di episode 2). Fungsi yang belum dipanggil tidak dikompilasi lebih dulu, sehingga alokasi memori saat startup lebih sedikit. Efeknya terasa di app dengan banyak modul — hanya kode yang benar-benar dijalankan yang membebani memori awal.
Bukan berarti menulis fungsi besar itu buruk; justru pastikan kode yang eksekusi awalnya kecil. Pindahkan modul berat agar dimuat saat dibutuhkan, misalnya dengan dynamic import. Ini strategi pembagian bundle yang sering dipakai bersama Hermes.
Hermes menyediakan optimizer bytecode yang diaktifkan dengan flag -O. Optimizer melakukan analisis di level bytecode: menghapus kode mati, menyatukan instruksi yang berlebihan, dan mengurangi register yang tidak terpakai. Contoh pemanggilan lengkap:
build/bin/hermesc \
-O \
-emit-binary \
-bundle \
-output-source-map \
index.js \
-out index.hbcBandingkan ukuran output dengan dan tanpa -O:
build/bin/hermesc -emit-binary -bundle index.js -out index-noopt.hbc
build/bin/hermesc -O -emit-binary -bundle index.js -out index-opt.hbc
ls -lh index-noopt.hbc index-opt.hbcFile dengan -O hampir selalu lebih kecil — dan ukuran yang lebih kecil berarti load dari disk lebih cepat. Pada bundle besar, perbedaannya bisa puluhan kilobyte atau lebih.
Flag -output-source-map menghasilkan source map sekaligus dengan bytecode, sehingga stack trace tetap bisa dipetakan ke source asli meski kode sudah dioptimalkan. Walaupun tidak langsung mempercepat startup, source map adalah prasyarat untuk mengukur dan memperbaiki performa di production — tanpanya kalian buta melihat error di mana terjadinya.
ls -lh index.hbc index.hbc.mapPasangan index.hbc dan index.hbc.map disimpan sebagai artifact build. Di episode 10 kita akan memakainya untuk membedah stack trace production.
Ukuran bundle berhubungan langsung dengan waktu load. Semakin besar file, semakin lama perangkat membacanya dari disk. Hubungannya hampir linear: bundle 15 MB dua kali lebih lambat di-load daripada 7,5 MB. Hermes membantu dua arah:
Namun jangan hanya bergantung pada Hermes. Kendalikan juga sumber ukuran:
Cara cepat mengukur dampaknya secara nyata: ukur waktu dari tap icon sampai layar pertama render. Di Android gunakan ADB:
adb shell am start -W -n com.belajarhermes/.MainActivityBaris TotalTime pada output adalah waktu dari launch sampai activity selesai — angka yang bisa dijadikan baseline sebelum dan sesudah optimisasi.
Sebelum menutup, biasakan membandingkan beberapa varian build dalam satu pipeline. Contoh skrip sederhana untuk benchmark ukuran:
for mode in "noopt" "opt"; do
if [ "$mode" = "opt" ]; then
build/bin/hermesc -O -emit-binary -bundle index.js -out index-$mode.hbc
else
build/bin/hermesc -emit-binary -bundle index.js -out index-$mode.hbc
fi
stat -c "%n %s bytes" index-$mode.hbc
doneCatat angka ini di tiap rilis. Jika sebuah dependency baru menaikkan ukuran bytecode secara drastis, kalian bisa menolaknya sebelum masuk production — bukan sesudahnya.
Startup Hermes kini bisa kalian kendalikan. Inilah yang wajib kalian bawa pulang:
-O mengaktifkan optimizer bytecode yang memperkecil dan mempercepat output.-output-source-map menghasilkan source map sebagai pasangan artifact bytecode.Selanjutnya, di episode 6 kita masuk ke topik memori: bagaimana Hades garbage collector bekerja, generational GC dan compacting, serta praktik meminimalkan memory churn di aplikasi React Native. Sampai jumpa!