Belajar JavaScript - Performance, Memory, Optimasi, dan Kode Siap Produksi
Episode 22 of 23

Belajar JavaScript - Performance, Memory, Optimasi, dan Kode Siap Produksi

Episode penutup menyatukan seluruh materi: mengukur performa dengan bukti, menghindari kebocoran memory, menerapkan pola debounce dan lazy loading, serta menyusun kode siap produksi dengan keamanan, pengujian, dan release yang terstruktur. Kalian menyelesaikan perjalanan Belajar JavaScript.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Selamat — kalian sudah sampai di episode terakhir. Dua puluh satu episode membangun pemahaman kalian dari sintaks dasar sampai tooling modern. Episode 22 menutup perjalanan dengan dua tema yang menentukan kualitas aplikasi di dunia nyata: performance dan readiness.

Performance berarti aplikasi tidak hanya berfungsi, tapi berfungsi cepat dan stabil — memuat ringan, merespons mulus, dan tidak bocor memory seiring waktu. Readiness berarti kode kalian aman, diuji, dan dirilis secara terstruktur. Keduanya adalah pembeda antara prototipe dan aplikasi produksi. Pegang satu prinsip sejak awal: jangan mengoptimasi tanpa bukti — ukur dulu, temukan masalah yang nyata, baru optimasi.

Mengukur Performa dengan Bukti

Performance API dan Timing

Sebelum mengubah apa pun, ukur. performance.now memberi waktu yang presisi:

JSMengukur durasi fungsi
function prosesData(angka) {
  let total = 0;
  for (const nilai of angka) {
    total += nilai * 2;
  }
  return total;
}
 
const mulai = performance.now();
const hasil = prosesData([1, 2, 3, 4, 5]);
const selesai = performance.now();
 
console.log(`Hasil: ${hasil}, durasi: ${selesai - mulai} ms`);

Menemukan Titik Lambat

Alat yang sudah kalian kenal dari episode 19 kembali berguna: tab Performance di DevTools merekam sesi dan menunjukkan di mana waktu benar-benar terbuang. Cari long tasks yang memblokir halaman, lalu periksa fungsi atau layout yang mendominasi. Hasil pengukuran menentukan prioritas — terkadang optimasi yang paling "keren" justru tidak berdampak apa pun pada aplikasi nyata.

Optimasi DOM dan Rendering

Batch Manipulasi DOM

Akses dan manipulasi DOM jauh lebih lambat daripada operasi di memori. Kumpulkan perubahan dan pasang sekaligus:

JSBatch manipulasi DOM
const kontainer = document.querySelector("#daftar");
const fragmen = document.createDocumentFragment();
 
for (let i = 1; i <= 100; i++) {
  const item = document.createElement("li");
  item.textContent = `Item ${i}`;
  fragmen.append(item);
}
 
kontainer.append(fragmen);

document.createDocumentFragment() menampung elemen di memori terlebih dahulu, lalu dipasang sekaligus. Tanpa ini, 100 penambahan berarti 100 kali memicu render; dengan fragment, browser merender sekali. Prinsip yang sama berlaku untuk reflow — perhitungan ulang layout yang mahal: kumpulkan perubahan style dalam satu batch, misalnya kotak.style.display = "none", lalu ubah class, baru tampilkan kembali, sehingga terjadi satu batch, bukan tiga reflow terpisah.

Memory dan Kebocoran

Penyebab Kebocoran

JavaScript mengelola memory dengan garbage collection — objek yang tidak lagi bisa diakses dibersihkan otomatis. Kebocoran memory terjadi ketika objek yang seharusnya sudah mati tetap bisa diakses, sehingga GC tidak berani membersihkannya. Penyebab paling umum di aplikasi web:

  • Event listener yang tidak dibuang pada elemen yang dihapus.
  • Referensi global yang menyimpan objek besar.
  • Closure yang menahan variabel dari scope yang sudah selesai.

Membuang Listener dengan Benar

Setiap addEventListener memegang referensi ke handler. Jika elemen dihapus tapi listener tidak dibuang, referensi tetap hidup:

JSMembuang event listener
function buatKartu() {
  const tombol = document.querySelector("#tombol");
 
  function handler() {
    console.log("Diklik");
  }
 
  tombol.addEventListener("click", handler);
 
  return function hapus() {
    tombol.removeEventListener("click", handler);
  };
}
 
const bersihkan = buatKartu();
bersihkan();

tombol.removeEventListener("click", handler) membuang listener dengan handler yang sama persis — itu sebabnya handler harus disimpan dalam variabel, bukan ditulis anonim inline. Fungsi hapus yang dikembalikan memberi kontrol kapan pembersihan terjadi.

Pola Optimasi Praktis

Debounce dan Throttle

Operasi mahal yang dipicu sering — pencarian saat mengetik, scroll, resize — bisa membanjiri aplikasi. Debounce menunda eksekusi sampai jeda aktivitas; throttle membatasi eksekusi maksimal satu kali per interval:

JSDebounce sederhana
function debounce(fungsi, jeda) {
  let timer = null;
 
  return function (...argumen) {
    clearTimeout(timer);
    timer = setTimeout(() => {
      fungsi(...argumen);
    }, jeda);
  };
}
 
const cari = debounce((kata) => {
  console.log("Mencari:", kata);
}, 300);

Lazy Loading dan Code Splitting

Memuat seluruh aplikasi sekaligus memperlambat kunjungan pertama. Code splitting memecah bundle menjadi bagian yang dimuat sesuai kebutuhan:

JSLazy loading modul
async function muatModulBerat() {
  const modul = await import("./modul-berat.js");
  return modul.proses();
}
 
tombol.addEventListener("click", () => {
  muatModulBerat().then(console.log);
});

Menyusun Kode Siap Produksi

Keamanan Dasar yang Tidak Bisa Ditawar

Kode produksi wajib mempertimbangkan keamanan. Dua aturan yang paling sering dilanggar:

  • Jangan memasukkan input pengguna ke innerHTML — celah XSS. Selalu pakai textContent atau escape HTML.
  • Jangan menyimpan token di localStorage — bisa dibaca skrip mana pun. Gunakan cookie HttpOnly.
JSMembuat teks aman untuk ditampilkan
function teksAman(teks) {
  const div = document.createElement("div");
  div.textContent = teks;
  return div.innerHTML;
}

div.textContent = teks membuat browser men-escape karakter khusus, sehingga <script> berubah menjadi teks biasa yang aman ditampilkan. Pola ini adalah trik sederhana untuk menampilkan input pengguna tanpa membuka celah.

Pengujian, Versioning, dan Release

Kode siap produksi juga berarti proses yang terstruktur:

  • Uji: tulis unit test untuk logika inti, minimal untuk fungsi murni.
  • Versi: pakai semantic versioning — major.minor.patch — untuk perubahan yang breaking, fitur, dan perbaikan.
  • CI: jalankan lint, test, dan build otomatis sebelum merge.
  • Release: rilis lewat proses otomatis, bukan men-deploy manual.

Semua alatnya sudah dibahas di episode 20 dan 21: lint dan format otomatis, build reproducible dengan lockfile, dan npm scripts yang bisa dipanggil CI. Menggabungkannya menjadi pipeline rilis adalah langkah terakhir menuju produksi.

Penutup

Episode 22 menutup perjalanan kalian: mengukur performa dengan performance.now dan tab Performance, mengoptimasi DOM dengan batching, mencegah kebocoran memory dengan membuang listener, menerapkan debounce dan lazy loading, serta menyusun kode produksi yang aman, teruji, dan dirilis terstruktur.

Inti yang harus dibawa pulang:

  • Jangan mengoptimasi tanpa mengukur — mulailah dari data.
  • Gunakan fragment dan batching untuk meminimalkan reflow DOM.
  • Kebocoran memory terjadi karena referensi yang tidak dibuang.
  • removeEventListener harus memakai handler yang sama persis.
  • Debounce menunda eksekusi; throttle membatasi frekuensi.
  • Escape input pengguna dan jangan simpan token di localStorage.
  • Uji, versi dengan semantic versioning, dan rilis lewat CI otomatis.

Ini adalah akhir dari series Belajar JavaScript. Dari episode 0 yang menyiapkan environment sampai episode 22 yang menyiapkan produksi, kalian telah membangun fondasi lengkap: sintaks, struktur data, fungsi, DOM, asynchronous, tooling, dan performa. Perjalanan sebenarnya dimulai sekarang — terapkan semua yang kalian pelajari di project sungguhan, dan teruslah menulis kode setiap hari. Selamat berkarya!

Belajar JavaScript - Performance, Memory, Optimasi, dan Kode Siap Produksi | Belajar JavaScript