Siklus feedback loop lokal yang lambat merupakan salah satu faktor utama degradasi developer experience (DX) pada proyek React Native skala menengah hingga besar. Kombinasi konvensional menggunakan Husky dan lint-staged sering kali menjadi bottleneck pada fase pre-commit. Saat repository membengkak dengan ratusan komponen, aset, dan kode native, proses validasi lokal sebelum commit dapat memakan waktu puluhan detik.
Masalah ini dapat diselesaikan dengan memigrasikan git hooks ke Lefthook, sebuah hook manager berbasis Go yang mendukung eksekusi tugas secara paralel, alokasi resource efisien, dan integrasi minim overhead ke dalam repository React Native.
Problem Bottleneck: Mengapa Husky dan Lint-Staged Melambat
Husky dan lint-staged mengandalkan runtime Node.js. Setiap kali developer menjalankan git commit, Node.js harus memuat runtime, mem-parsing script, dan mengeksekusi dependensi JavaScript satu per satu. Selain itu, proses git stashing internal milik lint-staged—yang dirancang untuk mengisolasi perubahan non-staged—memerlukan I/O disk signifikan pada repository yang memuat dependensi native kompleks.
Kelemahan mendasar alur konvensional meliputi:
- Overhead Startup Runtime: Node.js memerlukan puluhan hingga ratusan milidetik hanya untuk inisialisasi lingkungan eksekusi sebelum linter mulai berjalan.
- Eksekusi Serial Default: Lint-staged secara default menjalankan task secara sekuensial atau memiliki kontrol konkurensi terbatas terhadap proses multi-threading sistem operasi.
- Beban Stash Disk I/O: Operasi
git stashpada repositori React Native berukuran gigabyte memicu latensi tinggi dan risiko konflik stash saat commit dibatalkan di tengah jalan.
Arsitektur Lefthook: Keunggulan Komparatif
Lefthook dikompilasi ke dalam binary native Go mandiri tanpa dependensi runtime eksternal saat dieksekusi oleh Git. Fitur utamanya mencakup:
- Paralelisasi Asli (True Concurrency): Menjalankan linter, formatter, dan type checker secara bersamaan di thread CPU terpisah menggunakan goroutine.
- Filter Argumen Efisien: Menyediakan variabel interpolasi seperti
{staged_files}dan{all_files}yang diproses langsung di level binary sistem tanpa wrapper JavaScript tambahan. - Konfigurasi Deklaratif Tunggal: Seluruh konfigurasi git hooks didefinisikan dalam satu file
lefthook.ymltanpa memerlukan file skrip terpisah di direktori.husky/.
Instalasi dan Konfigurasi Dasar
Tambahkan Lefthook ke dalam devDependencies menggunakan package manager proyek:
# Menggunakan Yarn
yarn add -D @evilmartians/lefthook
# Menggunakan NPM
npm install --save-dev @evilmartians/lefthookInisialisasi konfigurasi Lefthook dengan membuat file lefthook.yml pada root direktori repositori:
# Inisialisasi hook git lokal
npx lefthook installKonfigurasi Komprehensif: lefthook.yml
Berikut adalah konfigurasi produksi lefthook.yml yang dioptimalkan untuk React Native. Konfigurasi ini menjalankan ESLint, Prettier, dan verifikasi TypeScript secara paralel pada staged files, mengecualikan folder native, serta menambahkan audit dependensi pada tahap pre-push.
# lefthook.yml
pre-commit:
parallel: true
commands:
eslint:
glob: "*.{js,jsx,ts,tsx}"
exclude:
- "android/"
- "ios/"
- "vendor/"
run: yarn eslint --cache --fix {staged_files}
stage_fixed: true
prettier:
glob: "*.{json,md,yml,yaml,css,scss}"
exclude:
- "android/"
- "ios/"
run: yarn prettier --write {staged_files}
stage_fixed: true
type-check:
glob: "*.{ts,tsx}"
run: yarn tsc --noEmit
pre-push:
parallel: false
commands:
audit:
run: yarn audit --level high
Menangani Batasan Type-Checking TypeScript
Kesalahan umum saat mengonfigurasi Git hooks adalah meneruskan daftar file yang di-stage ke TypeScript compiler, misalnya: tsc --noEmit {staged_files}. Perintah tersebut menyebabkan tsc mengabaikan opsi compilerOptions di dalam tsconfig.json, memutus resolusi path alias (seperti @components/*), dan menghilangkan deklarasi tipe global.
Solusi Lefthook: Menggunakan opsi glob: "*.{ts,tsx}" tanpa menyertakan placeholder {staged_files} pada atribut run. Lefthook mengevaluasi apakah ada file TypeScript di area staged. Jika ada, Lefthook menjalankan yarn tsc --noEmit secara utuh terhadap seluruh proyek. Jika tidak ada file TypeScript yang diubah, proses ini dilewati total (no-op).
Isolasi Aset dan Direktori Native
Aplikasi React Native mencakup folder android/ dan ios/ yang berisi kode Java/Kotlin, Objective-C/Swift, file resource Gradle, serta pods. Menyertakan direktori tersebut ke dalam validasi JavaScript menghabiskan resource.
Konfigurasi di atas menggunakan properti exclude untuk memblokir traversal ke sub-direktori native dan pihak ketiga. Selain itu, parameter stage_fixed: true memastikan bahwa modifikasi otomatis yang dilakukan oleh ESLint (--fix) atau Prettier (--write) langsung dimasukkan kembali ke staging git index secara aman.
Benchmark: Lefthook vs Husky + Lint-Staged
Pengujian dilakukan pada repositori React Native berukuran ~180 komponen TypeScript, dengan 12 staged files (kombinasi file .tsx dan .json).
| Metrik Pengujian | Husky + Lint-Staged (Sekuensial) | Lefthook (Paralel) | Dampak DX |
|---|---|---|---|
| Waktu Inisialisasi Hook | ~480 ms (Node runtime boot) | ~12 ms (Native Go binary) | 97% lebih cepat |
| Durasi Validasi (Lint + Typecheck) | 7.20 detik | 2.45 detik | ~66% reduksi durasi |
| Overhead Stash Index | Tinggi (Stash/Unstash via JS) | Rendah (Penyimpanan memori internal) | Bebas disk churn |
| Total Durasi Pre-Commit | ~7.68 detik | ~2.46 detik | Siklus commit 3.1x lebih cepat |
Troubleshoot: Mengatasi Hook Terlewat di Lingkungan Tim
Masalah berulang dalam implementasi Git hook di tim adalah developer baru yang melakukan clone repositori namun hook tidak tereksekusi secara otomatis.
1. Otomasi Instalasi via Lifecycle Script
Pastikan binary Lefthook terdaftar ke direktori .git/hooks/ setiap kali proses instalasi dependensi selesai. Tambahkan script prepare pada package.json:
// package.json
{
"scripts": {
"prepare": "lefthook install"
}
}
NPM dan Yarn otomatis mengeksekusi prepare setelah npm install atau yarn install berhasil dilakukan di mesin lokal developer atau CI.
2. Konflik Konfigurasi core.hooksPath
Jika Husky pernah digunakan sebelumnya, konfigurasi Git global atau lokal mungkin masih mengarah ke folder lain. Periksa nilai hook path:
git config --local --get core.hooksPathJika output menunjukkan direktori selain .git/hooks (misalnya .husky), hapus konfigurasi tersebut agar Lefthook dapat mengambil alih:
git config --local --unset core.hooksPath
npx lefthook install3. Bypass GUI Git Client
Aplikasi GUI Git (seperti Sourcetree, VS Code Git, atau GitKraken) sering kali gagal menemukan path binary node atau yarn saat hook dieksekusi karena perbedaan environment variable PATH sistem operasi (terutama di macOS). Pastikan symlink Node runtime terdeteksi di /usr/local/bin atau deklarasikan environment shell di ~/.zshrc / ~/.bashrc agar hook dapat mengenali command package manager.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!