Entropi front-end itu nyata. Sebuah codebase tidak runtuh dalam semalam. Ia menumpuk. Suatu hari Selasa Anda menambahkan library pemformatan tanggal. Enam bulan kemudian seseorang menambahkan yang lain karena mereka tidak menemukan yang pertama. Polyfill menumpuk untuk browser yang tidak lagi Anda dukung. Build tools berlapis-lapis. Akhirnya, folder node_modules menjadi laci barang bekas digital di mana tidak ada yang bisa dibuang tanpa rasa takut. Anda berhenti memperbarui. Lalu Anda berhenti melihatnya. Saat itulah setiap perubahan kecil berubah menjadi sebuah perjudian.
Saya menabrak tembok ini saat mencoba memperbarui Material UI di proyek lama. Saya membuka package.json dan nyaris tidak mengenali setengah dari entri yang ada. Puluhan library ada di sana, beberapa sudah kedaluwarsa bertahun-tahun, yang lain begitu tidak jelas sehingga saya harus memeriksa git blame untuk mencari tahu siapa yang menambahkannya dan mengapa. Saya menjalankan perintah install untuk versi Material UI yang baru dan terminal menyala dengan peringatan peer dependency. Package yang ingin saya perbarui sebenarnya baik-baik saja. Ekosistem di sekitarnya yang bermasalah. Saya menyadari bahwa saya tidak sedang melakukan upgrade. Saya sedang mengekskavasi reruntuhan.
Mengapa Kekacauan Ini Berbiaya Lebih Mahal daripada Gengsi
Mengabaikan dependensi bukanlah masalah kosmetik. Hal ini menciptakan masalah nyata yang mahal.
Risiko keamanan adalah ancaman yang nyata. Package yang ditinggalkan membawa kerentanan yang telah diungkapkan yang ditandai oleh scanner setiap minggu. Lebih buruk lagi, library yang Anda instal secara langsung mungkin baik-baik saja, sementara transitive dependencies yang mereka tarik tidak. Anda mewarisi technical debt orang lain tanpa menyadarinya.
Biaya berlipat ganda seiring jarak. Semakin lama Anda menunggu, semakin lebar kesenjangan versinya. Melompat satu versi major React adalah sebuah pekerjaan. Melompat tiga versi adalah proyek migrasi yang bisa memakan waktu berminggu-minggu. Anda berhenti mendapatkan perbaikan bug, peningkatan performa, dan kompatibilitas dengan tooling modern. Tim akhirnya membangun di sekitar batasan yang sebenarnya sudah tidak ada lagi.
Library bisa mati. Sebuah package tanpa maintainer aktif secara default menjadi fork pribadi Anda. Saat ia rusak, Andalah yang harus membaca minified source code-nya di tengah malam. Komunitas telah beralih ke solusi yang lebih baik, dan tim Anda terjebak mempertahankan sebuah hantu.
Velocity anjlok. Developer baru menghabiskan hari-hari pertama mereka mempelajari API yang aneh untuk alat-alat yang telah digantikan oleh standar web atau alternatif mainstream. Alih-alih merilis fitur, senior engineer Anda malah menjadi sejarawan, menjelaskan mengapa proyek ini masih menggunakan task runner dari tahun 2015.
Audit Sebelum Menyentuh Satu Versi Pun
Kesalahan terburuk adalah menjalankan update secara membabi buta dan berharap tesnya lolos. Mulailah dengan audit. Ambil package.json dan selidiki setiap entri.
Ajukan empat pertanyaan:
- Apa masalah yang diselesaikan ini?
- Di mana tepatnya kita menggunakannya?
- Apakah ini masih diperlukan?
- Apakah ada alternatif yang lebih baik sekarang?
Anda akan menemukan redundansi. Mungkin moment dan date-fns sama-sama ada di daftar karena dua developer menyelesaikan masalah yang sama di waktu yang berbeda. Mungkin sebuah polyfill untuk Internet Explorer masih disertakan padahal analitik Anda menunjukkan nol trafik dari browser lama. Mungkin wrapper kustom di sekitar fetch bisa dihapus karena browser modern menangani edge case secara native.
Terkadang penggantian lebih baik daripada pembaruan. Berjuang dengan library charting yang ditinggalkan melalui tiga tahun breaking changes bisa memakan waktu lebih lama daripada menggantinya dengan alternatif yang stabil dan membangun ulang beberapa komponen. Bersiaplah untuk mengurangi.
Lapisan Tersembunyi: Transitive Dependencies dan Semver
Dependensi langsung hanyalah bagian atas dari gunung es. Bagian besarnya berada di bawah dalam bentuk transitive dependencies, yaitu package yang dibutuhkan oleh package Anda. Anda tidak memilihnya, tetapi mereka dijalankan dalam build Anda. Mereka membengkakkan bundle Anda, memperluas permukaan serangan, dan terkadang konflik satu sama lain dengan cara yang menghasilkan error build yang membingungkan.
Anda perlu memahami semantic versioning sebagaimana adanya, bukan sebagaimana yang Anda harapkan.
- Major updates: Ini adalah migrasi. Perlakukan sebagai breaking changes sampai terbukti sebaliknya. Baca changelog, alokasikan waktu, dan uji secara menyeluruh.
- Minor updates: Ini menambahkan fitur. Mereka juga dapat mengubah perilaku dengan cara yang halus. Jangan berasumsi ini gratis.
- Patch updates: Ini memperbaiki bug. Biasanya aman, tetapi jika kode Anda bergantung pada bug tersebut, atau jika patch mengubah sesuatu yang Anda lakukan monkey-patching, Anda tetap bisa mengalami error.
Mengetahui aturan-aturan ini membantu Anda mengategorikan risiko sebelum menyentuh apa pun.
Gunakan Alat Anda Seperti Seorang Pengrajin
Jika Anda menggunakan Yarn, beberapa perintah bawaan mengubah tebakan menjadi sebuah proses.
Jalankan yarn outdated terlebih dahulu. Ini memberi Anda gambaran tentang apa yang telah bergeser
