Membedah pipeline build Hermes di React Native: bagaimana Metro bundler mengubah source menjadi bundle, peran HermesBytecodePlugin yang mengkompilasi bundle menjadi bytecode HBC, opsi bundle-command dan hermesc untuk kendali penuh, hingga produksi artifact output, source maps, dan debugging symbol.

Di episode 3 Hermes sudah aktif di project kalian. Sekarang kita lihat apa yang sebenarnya terjadi saat kalian menjalankan perintah build. Di sanalah Hermes bertemu Metro bundler — dan di situlah bytecode lahir.
Episode 4 membedah pipeline build: integrasi Metro dengan HermesBytecodePlugin, opsi bundle-command dan hermesc, serta cara membaca artifact output, source maps, dan debugging symbol.
Sebuah bundle React Native melewati dua tahap. Tahap pertama: Metro membaca seluruh modul JavaScript dan menggabungkannya menjadi satu file bundle. Tahap kedua: hermesc mengompilasi bundle itu menjadi bytecode HBC.
source modules --> Metro bundler --> bundle.js
|
v
HermesBytecodePlugin
|
v
bundle.hbc (+ .map)HermesBytecodePlugin adalah penghubung keduanya — ia memanggil hermesc di akhir proses bundling. Di React Native modern, plugin ini terpasang otomatis oleh Metro config bawaan.
Metro memakai file metro.config.js untuk mengatur transform dan bundling. Di React Native dengan Hermes, konfigurasi default sudah menyertakan HermesBytecodePlugin lewat bantuan helper getDefaultConfig. Contoh konfigurasi minimum:
const { getDefaultConfig } = require("@react-native/metro-config");
const config = getDefaultConfig(__dirname);
module.exports = config;Di balik layar, helper ini mendaftarkan HermesBytecodePlugin sebagai bundle plugin — sebuah hook yang dijalankan Metro setelah bundle JavaScript dihasilkan. Hasil akhirnya adalah file bytecode yang dimuat React Native di runtime.
Secara detail, plugin ini melakukan dua hal:
hermesc dengan flag yang sudah dikalibrasi untuk React Native..hbc, bukan .js.Jika kalian ingin melihat plugin ini secara eksplisit di konfigurasi, gunakan HermesBytecodePlugin langsung dari package React Native:
const { getDefaultConfig } = require("@react-native/metro-config");
const HermesBytecodePlugin = require("react-native/HermesBytecodePlugin");
const config = getDefaultConfig(__dirname);
config.transformer.bundlePlugins = [HermesBytecodePlugin];
module.exports = config;Plugin ini membaca konfigurasi seperti opsi compiler yang disetel di file package.json React Native. Untuk kendali penuh atas compiler, kalian bisa menimpa lewat opsi yang kita bahas berikutnya.
Cara paling fleksibel mengendalikan pipeline adalah dengan bundle-command — opsi yang memberitahu React Native untuk memanggil command custom alih-alih default. Ini berguna untuk build pipeline di CI atau eksperimen bytecode. Contoh penggunaan:
npx react-native bundle \
--platform android \
--dev false \
--entry-file index.js \
--bundle-output dist/index.android.bundleCommand ini tetap menghasilkan bundle JavaScript biasa; kompilasi bytecode tetap dilakukan oleh plugin bawaan. bundle-command berguna saat kalian ingin menambahkan langkah post-processing setelah Metro selesai — misalnya mengukur ukuran bundle atau menandatanganinya.
Untuk eksperimen, panggil hermesc secara langsung (binary dari episode 3) tanpa Metro sama sekali:
build/bin/hermesc \
-O \
-emit-binary \
-output-source-map \
-bundle \
-w=-0 \
index.js \
-out dist/index.android.bundle.hbcPenjelasan flag:
-emit-binary — menghasilkan file bytecode .hbc.-bundle — menandai bahwa input adalah bundle Metro, bukan modul tunggal.-output-source-map — menghasilkan source map untuk debugging.-w=-0 — menonaktifkan peringatan error yang sebenarnya hanya warning.-O — mengaktifkan optimizer; detail lengkap di episode 5.Setelah build, periksa apa saja yang dihasilkan di folder android/app/build/generated/assets (Android) atau di direktori output bundle:
dist/
index.android.bundle <- bundle JS (Metro)
index.android.bundle.hbc <- bytecode Hermes (hasil hermesc)
index.android.bundle.map <- source mapBerkas .hbc inilah yang akhirnya di-embedd ke APK. Ukurannya biasanya lebih kecil dari bundle JS karena bytecode lebih padat — dan ini yang akan kita optimisasi di episode 5.
Source map menghubungkan bytecode dengan kode sumber asli, sehingga stack trace yang dilaporkan app bisa dipetakan kembali ke file dan baris yang sebenarnya. Hermes menghasilkan source map lewat flag -output-source-map di atas. Di React Native, source map diproduksi otomatis saat build release:
npx react-native run-android --mode releaseSource map release dihasilkan di folder dist project. Tanpa source map, error di production hanya menampilkan posisi bytecode yang tidak terbaca manusia — masalah yang kita tuntaskan di episode 10.
Warning
Source map memuat pemetaan ke source asli. Untuk aplikasi production, pastikan source map tidak ikut ter-embedd ke APK — simpan di backend symbol server dan jaga agar tidak bocor, karena bisa membuka source code kalian.
Selain source map, Hermes menyediakan debugging symbol untuk tool seperti Android Studio. Saat build release, React Native menghasilkan file map dengan hermesc yang memuat informasi symbol untuk stack trace native. Untuk mengunduh symbol saat crash, SDK tools biasanya mencari file .symbol yang dihasilkan dari -output-source-map bersama -emit-binary. Inilah yang dipakai layanan crash reporting untuk menerjemahkan crash Hermes ke lokasi asli di source.
Pipeline build Hermes sudah terpetakan. Inilah yang wajib kalian bawa pulang:
HermesBytecodePlugin mengkompilasinya menjadi .hbc.HermesBytecodePlugin terpasang otomatis di React Native modern; bisa juga dipasang eksplisit di metro.config.js.bundle-command dan pemanggilan hermesc langsung memberi kendali penuh atas pipeline.Selanjutnya, di episode 5 kita mengoptimisasi: prepackaging bytecode, flag optimizer -O, dan bagaimana ukuran bundle memengaruhi cold start. Sampai jumpa!