Tree Shaking: apa itu, mekanisme penghapusan kode mati dan alat

Penulis: IT Sectr Diterbitkan: 2026-05-18 Waktu membaca: 8 mnt

Tree Shaking — mekanisme penghapusan kode yang tidak digunakan (dead code elimination) pada tahap pembangunan aplikasi. Tree Shaking menganalisis struktur statis modul ES dan mengecualikan fungsi, kelas, dan variabel yang diekspor tetapi tidak diimpor di mana pun. Menurut Webpack Documentation, konfigurasi Tree Shaking yang benar dapat mengurangi ukuran bundel sebesar 30–60% tanpa mengubah fungsionalitas aplikasi.

Poin Utama

  • Tree Shaking — penghapusan ekspor yang tidak digunakan dari modul ES berdasarkan analisis statis import/export
  • Modul ES (import/export) — satu-satunya format yang mendukung Tree Shaking; CommonJS tidak didukung
  • Webpack dan Rollup — pembangun utama dengan dukungan Tree Shaking melalui plugin
  • Side effects — efek samping dalam modul memblokir Tree Shaking; flag sideEffects: false di package.json memecahkan masalah
  • Used exports — analisis penggunaan ekspor dalam mode produksi Webpack untuk penghapusan kode mati yang akurat

Apa itu Tree Shaking?

Tree Shaking (mengguncang pohon) — teknik optimasi kode di mana modul dan fungsi yang tidak digunakan dalam aplikasi dikeluarkan dari bundel final. Istilah ini diperkenalkan oleh tim Rollup pada tahun 2015 dan secara metaforis menggambarkan proses: pohon dependensi diguncang, dan cabang yang tidak digunakan akan jatuh. Tidak seperti optimasi manual, Tree Shaking dilakukan secara otomatis pada tahap pembangunan.

Tree Shaking hanya bekerja dengan modul ES (ECMAScript Modules), di mana dependensi ditentukan secara statis melalui import dan export. CommonJS (require/module.exports) tidak mendukung Tree Shaking karena require dijalankan secara dinamis — pembangun tidak dapat menentukan sebelumnya fungsi mana yang benar-benar digunakan. Pustaka modern (Lodash, Moment.js, RxJS) merilis versi ES untuk mendukung Tree Shaking.

Rollup: pionir Tree Shaking

Rollup — pembangun pertama yang mengimplementasikan Tree Shaking pada tahun 2015. Tidak seperti Webpack, Rollup sejak awal dirancang untuk modul ES dan melakukan penghapusan kode mati yang lebih agresif. Rollup menganalisis tidak hanya ekspor individu, tetapi juga seluruh modul: jika modul tidak memiliki efek samping dan tidak ada ekspor yang digunakan, Rollup mengecualikan seluruh modul dari bundel.

Rollup sangat efektif untuk pustaka dan SDK, di mana setiap kilobyte berarti. Framework Vue.js menggunakan Rollup untuk membangun versi produksi. React beralih ke Rollup pada tahun 2020. Untuk aplikasi, Webpack lebih sering digunakan karena ekosistem plugin yang lebih kaya (Hot Module Replacement, code splitting, CSS modules), tetapi untuk Tree Shaking maksimal saat membangun pustaka, Rollup tetap menjadi standar industri.

Penghematan dari Tree Shaking sangat tergantung pada arsitektur proyek. Dalam aplikasi React dengan pustaka Ant Design, Tree Shaking dapat menghapus hingga 70% kode komponen UI. Dalam proyek di mana semua impor bersifat spesifik dan tepat, penghematan akan mencapai 5–15%. Penghematan rata-rata menurut penelitian Webpack adalah 30–40% dari ukuran bundel.

Apa itu kode mati

Tipe kode matiContohDeteksi oleh Tree Shaking
Ekspor tidak digunakanexport function unusedHelper()Ya
Import tidak digunakanimport { unused } from "lib"Ya
Cabang kondisi matiif (false) { ... }Tidak (dihapus oleh minifier)
Fungsi tidak dipanggil setelah DCEfunction a(){} a() di mana a tidak dipanggilSebagian

Bagaimana Tree Shaking bekerja: analisis statis modul

Mekanisme Tree Shaking didasarkan pada grafik dependensi (dependency graph) yang dibangun oleh pembangun dari semua import/export dalam proyek. Pada tahap pertama, pembangun menelusuri semua file dari titik masuk (entry point) dan mengumpulkan pohon modul. Pada tahap kedua, dianalisis ekspor mana dari setiap modul yang benar-benar diimpor di modul lain.

Untuk setiap modul, Webpack atau Rollup menandai ekspor sebagai digunakan atau tidak digunakan. Ekspor yang tidak digunakan dikeluarkan dari bundel. Namun modul itu sendiri tetap berada di bundel jika setidaknya satu ekspornya digunakan. Mengecualikan modul sepenuhnya hanya dapat dilakukan melalui flag sideEffects atau jika modul tidak mengandung efek samping apa pun.

Contoh: sebelum dan sesudah Tree Shaking

js
// utils.js — modul dengan fungsi
export function formatDate(date) {
  return date.toISOString().slice(0, 10);
}

export function formatCurrency(amount) {
  return "$" + amount.toFixed(2);
}

export function slugify(text) {
  return text.toLowerCase().replace(/\s+/g, "-");
}
js
// app.js — titik masuk
import { formatDate } from "./utils";

const today = formatDate(new Date());
console.log(today);
js
// Setelah Tree Shaking — di bundel hanya formatDate
function formatDate(date) {
  return date.toISOString().slice(0, 10);
}
const today = formatDate(new Date());
console.log(today);

Tree Shaking mengecualikan formatCurrency dan slugify dari bundel final karena tidak diimpor di app.js. Ukuran modul utils.js berkurang dari 3 fungsi menjadi 1. Jika utils.js mengandung side effects (misalnya, inisialisasi global), Tree Shaking tidak akan dapat menghapus bahkan ekspor yang tidak digunakan.

Tree Shaking di Webpack: konfigurasi dan optimasi

Webpack menyertakan dukungan bawaan untuk Tree Shaking melalui plugin TerserPlugin dalam mode produksi. Untuk mengaktifkan Tree Shaking, dua kondisi sudah cukup: mode diatur ke production (mode: "production") dan modul menggunakan sintaks ES (import/export). Webpack secara otomatis menandai ekspor yang tidak digunakan dan mengirimkannya ke Terser untuk dihapus.

Konfigurasi tambahan usedExports: true di optimization.webpack.config.js mengaktifkan analisis detail penggunaan ekspor di dalam modul. Opsi ini menentukan ekspor mana yang benar-benar digunakan (used) dan mana yang hanya diekspor (provided). Kombinasi usedExports dan Terser memberikan efisiensi maksimum penghapusan kode mati.

Konfigurasi Webpack untuk Tree Shaking

js
// webpack.config.js — konfigurasi Tree Shaking
module.exports = {
  mode: "production",
  entry: "./src/app.js",
  output: {
    filename: "bundle.js",
  },
  optimization: {
    usedExports: true,
    minimize: true,
    concatenateModules: true,
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules\/(?!(my-lib)\/).*/,
        use: {
          loader: "babel-loader",
          options: {
            presets: [
              ["@babel/preset-env", { modules: false }],
            ],
          },
        },
      },
    ],
  },
};

Parameter kunci — modules: false di @babel/preset-env. Babel secara default mengubah modul ES menjadi CommonJS, yang membunuh Tree Shaking. modules: false melarang Babel mengubah import/export, mempertahankan sintaks ES untuk Webpack. concatenateModules juga menggabungkan modul ke dalam ruang lingkup bersama, mengurangi jumlah IIFE dan ukuran bundel.

Masalah side effects dan flag sideEffects

Side effects (efek samping) — tindakan modul saat diimpor yang tidak terkait dengan nilai yang diekspor: gaya global (import "./styles.css"), polyfill (import "core-js/stable"), inisialisasi variabel global atau pendaftaran Service Worker. Jika modul mengandung side effects, pembangun tidak dapat dengan aman menghapusnya dari bundel, bahkan jika tidak ada ekspor yang digunakan.

Flag sideEffects di package.json memberi tahu pembangun modul mana dalam paket yang tidak memiliki efek samping. Untuk paket di mana semua modul murni (hanya ekspor fungsi), harus diatur "sideEffects": false. Untuk paket dengan CSS atau polyfill — array jalur ke file dengan efek samping: "sideEffects": ["*.css"]. Tanpa flag ini, Tree Shaking tidak akan menghapus bahkan fungsi yang tidak digunakan.

Cara menentukan side effects dalam kode Anda

Untuk memeriksa apakah modul memiliki efek samping, ajukan pertanyaan: akankah import ini melakukan tindakan apa pun yang tidak terkait dengan ekspor nilai? import "./styles.css" menambahkan CSS ke DOM — ini adalah side effect. import { throttle } from "lodash-es" tidak memiliki side effects — hanya membuat fungsi throttle tersedia. Polyfill (import "core-js/stable") memiliki side effects — mereka memodifikasi prototipe global.

Untuk modul Anda sendiri, disarankan: memindahkan gaya dan polyfill ke titik masuk terpisah, memisahkan utilitas murni (fungsi tanpa side effects) dari modul dengan efek samping (inisialisasi, logging, pendaftaran Service Worker). Di package.json proyek tingkat atas, atur "sideEffects": false hanya jika semua modul murni. Jika ada gaya — atur "sideEffects": ["*.css"] secara tepat.

Contoh konfigurasi sideEffects

json
{
  "name": "my-ui-lib",
  "version": "2.1.0",
  "sideEffects": [
    "*.css",
    "polyfills.js"
  ],
  "module": "dist/index.esm.js",
  "main": "dist/index.cjs.js"
}

"sideEffects": ["*.css", "polyfills.js"] berarti: semua file CSS memiliki efek samping (tidak dapat dihapus) dan polyfills.js juga. Semua file JS lain dalam paket murni — dapat di-shake dengan aman. Bidang module menunjukkan jalur ke versi ES paket yang harus digunakan pembangun sebagai pengganti versi CommonJS (main) untuk Tree Shaking.

Tree Shaking di React Native dan Metro

React Native dengan Metro Bundler mendukung versi terbatas Tree Shaking. Metro tidak melakukan analisis statis lengkap dari ekspor yang digunakan (usedExports) seperti Webpack. Sebagai gantinya, Metro mengandalkan Terser untuk menghapus bagian modul yang tidak digunakan pada tahap minifikasi. Efisiensi pendekatan ini lebih rendah daripada Tree Shaking penuh di Webpack.

Untuk optimasi maksimal proyek React Native disarankan: menggunakan pustaka dengan modul ES (bidang module di package.json), menghubungkan plugin babel-plugin-transform-remove-console untuk menghapus kode debug, dan mengkonfigurasi Metro transformer.minifierConfig untuk Terser. Selain itu, Ram Bundle (pembagian bundel menjadi modul) mengurangi pemuatan layar yang tidak digunakan.

Pertanyaan yang Sering Diajukan

Mengapa Tree Shaking tidak berfungsi dengan CommonJS?

CommonJS (require/module.exports) tidak mendukung analisis statis — require dapat dipanggil secara dinamis di dalam kondisi dan fungsi. Pembangun tidak dapat menentukan bagian modul mana yang benar-benar digunakan. Hanya modul ES dengan import/export statis yang memungkinkan Tree Shaking.

Bisakah Tree Shaking digunakan dengan TypeScript?

TypeScript sepenuhnya kompatibel dengan Tree Shaking asalkan tsconfig.json dikonfigurasi untuk modul ES: "module": "esnext". Kompiler TypeScript harus mempertahankan import/export tanpa konversi ke CommonJS. Babel dengan @babel/preset-typescript dan modules: false juga meneruskan modul ES ke Webpack dengan benar.

Bagaimana cara memeriksa apakah Tree Shaking berhasil?

Webpack Bundle Analyzer — plugin yang memvisualisasikan komposisi bundel dalam bentuk diagram interaktif. Jika pustaka ada di bundel tetapi fungsinya tidak digunakan, Tree Shaking tidak berhasil. Juga dapat menganalisis file output: temukan ekspor yang tidak digunakan dalam teks bundel melalui grep.

Mengapa Lodash tidak di-tree-shake secara default?

Lodash v4 didistribusikan sebagai paket CommonJS. Untuk Tree Shaking, gunakan lodash-es — versi ES dari pustaka. Ganti import throttle from "lodash/throttle" dengan import { throttle } from "lodash-es" dan konfigurasi resolve.alias di Webpack untuk mengganti lodash dengan lodash-es.

Apakah Tree Shaking mempengaruhi waktu build?

Tree Shaking sedikit meningkatkan waktu build (sebesar 5–15%), karena menambahkan tahap analisis grafik dependensi dan penandaan ekspor yang digunakan. Dalam mode development, Tree Shaking biasanya dinonaktifkan untuk kecepatan. Dalam produksi, waktu tambahan diimbangi oleh pengurangan ukuran bundel yang signifikan.

Kesimpulan

  • Tree Shaking — penghapusan otomatis ekspor ES yang tidak digunakan pada tahap build, mengurangi ukuran bundel sebesar 30–60%
  • Modul ES — satu-satunya format yang mendukung analisis statis; CommonJS tidak cocok untuk Tree Shaking
  • Webpack dan Rollup menyediakan Tree Shaking melalui usedExports dan Terser dalam mode produksi
  • Side effects memblokir penghapusan modul; flag sideEffects: false di package.json memecahkan masalah untuk pustaka murni
  • Babel harus dikonfigurasi dengan modules: false agar tidak mengubah modul ES menjadi CommonJS
  • React Native Metro memiliki Tree Shaking terbatas, mengandalkan Terser pada tahap minifikasi

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga