Tree Shaking, uygulama derleme aşamasında kullanılmayan kodu temizleme (dead code elimination) mekanizmasıdır. Tree Shaking, ES modüllerinin statik yapısını analiz eder ve hiçbir yerde import edilmeyen dışa aktarılmış (export) fonksiyonları, sınıfları ve değişkenleri hariç tutar. Webpack Documentation'a göre, Tree Shaking'in doğru yapılandırılması, uygulama işlevselliğini değiştirmeden bundle boyutunu %30–60 oranında azaltabilir.
Kilit Noktalar
Tree Shaking, son bundle'dan kullanılmayan modülleri ve fonksiyonları hariç tutan bir kod optimizasyon tekniğidir. Terim, 2015 yılında Rollup ekibi tarafından tanıtılmıştır ve süreci mecazi olarak tanımlar: bağımlılık ağacı sallanır (shake) ve kullanılmayan dallar düşer. Manuel optimizasyonun aksine Tree Shaking, derleme aşamasında otomatik olarak gerçekleştirilir.
Tree Shaking yalnızca ES modülleri (ECMAScript Modules) ile çalışır; burada bağımlılıklar import ve export aracılığıyla statik olarak belirlenir. CommonJS (require/module.exports), Tree Shaking'i desteklemez çünkü require dinamik olarak çalıştırılır — bundler hangi fonksiyonların gerçekten kullanıldığını önceden belirleyemez. Modern kütüphaneler (Lodash, Moment.js, RxJS), Tree Shaking'i desteklemek için ES sürümlerini yayınlar.
Rollup, 2015 yılında Tree Shaking'i uygulayan ilk bundler'dır. Webpack'in aksine Rollup, baştan itibaren ES modülleri için tasarlanmıştır ve daha agresif bir şekilde ölü kod temizliği yapar. Rollup yalnızca bireysel exportları değil, tüm modülleri analiz eder: bir modülün yan etkisi yoksa ve hiçbir export kullanılmıyorsa, Rollup tüm modülü bundle'dan çıkarır.
Rollup, her kilobaytın önemli olduğu kütüphaneler ve SDK'lar için özellikle etkilidir. Vue.js framework'ü, üretim sürümünü oluşturmak için Rollup kullanır. React, 2020 yılında Rollup'a geçmiştir. Uygulamalar için, daha zengin eklenti ekosistemi (Hot Module Replacement, code splitting, CSS modules) nedeniyle Webpack daha yaygın kullanılır, ancak kütüphane oluştururken maksimum Tree Shaking için Rollup endüstri standardı olmaya devam etmektedir.
Tree Shaking'ten elde edilen tasarruf, proje mimarisine büyük ölçüde bağlıdır. Ant Design kütüphanesini kullanan bir React uygulamasında Tree Shaking, UI bileşen kodunun %70'ine kadarını kaldırabilir. Tüm importların belirli ve hedefe yönelik olduğu bir projede tasarruf %5–15 olacaktır. Webpack araştırmalarına göre ortalama tasarruf, bundle boyutunun %30–40'ıdır.
| Ölü Kod Türü | Örnek | Tree Shaking Tespiti |
|---|---|---|
| Kullanılmayan export | export function unusedHelper() | Evet |
| Kullanılmayan import | import { unused } from "lib" | Evet |
| Ölü koşul dalı | if (false) { ... } | Hayır (küçültücü tarafından kaldırılır) |
| DCE sonrası çağrılmayan fonksiyon | function a(){} a() burada a çağrılmamış | Kısmen |
Tree Shaking mekanizması, bundler'ın projedeki tüm import/export ifadelerinden oluşturduğu bir bağımlılık grafiğine (dependency graph) dayanır. İlk aşamada, bundler giriş noktasından (entry point) tüm dosyaları dolaşır ve modül ağacını toplar. İkinci aşamada, her modülten hangi exportların diğer modüllerde gerçekten import edildiğini analiz eder.
Her modül için Webpack veya Rollup, exportları kullanılmış veya kullanılmamış olarak işaretler. Kullanılmayan exportlar bundle'dan çıkarılır. Ancak, modülün kendisi, exportlarından en az biri kullanılıyorsa bundle'da kalır. Bir modül, yalnızca sideEffects bayrağı aracılığıyla veya modülün hiçbir yan etkisi yoksa tamamen çıkarılabilir.
// utils.js — fonksiyonlar içeren modül
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, "-");
}// app.js — giriş noktası
import { formatDate } from "./utils";
const today = formatDate(new Date());
console.log(today);// Tree Shaking sonrası — bundle'da yalnızca formatDate
function formatDate(date) {
return date.toISOString().slice(0, 10);
}
const today = formatDate(new Date());
console.log(today);Tree Shaking, app.js'de import edilmedikleri için formatCurrency ve slugify'ı son bundle'dan çıkarmıştır. utils.js modülünün boyutu 3 fonksiyondan 1'e düşmüştür. utils.js yan etkiler içeriyorsa (örneğin, küresel başlatma), Tree Shaking kullanılmayan exportları bile kaldıramaz.
Webpack, üretim modunda TerserPlugin aracılığıyla yerleşik Tree Shaking desteği içerir. Tree Shaking'i etkinleştirmek için iki koşul yeterlidir: mode production olarak ayarlanmış olmalı (mode: "production") ve modüller ES sözdizimini (import/export) kullanmalıdır. Webpack, kullanılmayan exportları otomatik olarak işaretler ve kaldırma işlemi için Terser'a iletir.
optimization.webpack.config.js içindeki usedExports: true ek yapılandırması, bir modül içindeki export kullanımının ayrıntılı analizini sağlar. Bu seçenek, hangi exportların gerçekten kullanıldığını ve hangilerinin yalnızca dışa aktarıldığını (provided) belirler. usedExports ve Terser kombinasyonu, maksimum ölü kod temizleme verimliliği sağlar.
// webpack.config.js — Tree Shaking yapılandırması
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 }],
],
},
},
},
],
},
};Anahtar parametre, @babel/preset-env içindeki modules: false'dur. Varsayılan olarak Babel, ES modüllerini CommonJS'ye dönüştürür ve bu da Tree Shaking'i öldürür. modules: false, Babel'in import/export'u dönüştürmesini engeller ve Webpack için ES sözdizimini korur. concatenateModules ayrıca modülleri ortak bir kapsamda birleştirir, IIFE sayısını azaltır ve bundle boyutunu küçültür.
Side effects (yan etkiler), bir modülün import edildiğinde gerçekleştirdiği ve dışa aktarılan değerlerle ilgili olmayan eylemlerdir: küresel stiller (import "./styles.css"), polyfill'ler (import "core-js/stable"), küresel değişken başlatma veya Service Worker kaydı. Bir modül yan etkiler içeriyorsa, bundler, exportlarından hiçbiri kullanılmasa bile onu bundle'dan güvenle kaldıramaz.
package.json'daki sideEffects bayrağı, paketteki hangi modüllerin yan etkisi olmadığını bundler'a bildirir. Tüm modüllerin saf (yalnızca fonksiyon exportları) olduğu bir paket için "sideEffects": false belirtilmelidir. CSS veya polyfill içeren paketler için — yan etkileri olan dosyaların yollarının bir dizisi: "sideEffects": ["*.css"]. Bu bayrak olmadan Tree Shaking, kullanılmayan fonksiyonları bile kaldırmaz.
Bir modülün yan etkileri olup olmadığını kontrol etmek için şu soruyu sorun: Bu import, değer dışa aktarmayla ilgili olmayan herhangi bir eylem gerçekleştirecek mi? import "./styles.css" DOM'a CSS ekler — bu bir yan etkidir. import { throttle } from "lodash-es"'in yan etkisi yoktur — yalnızca throttle fonksiyonunu kullanılabilir hale getirir. Polyfill'ler (import "core-js/stable") yan etkilere sahiptir — küresel prototipleri değiştirirler.
Kendi modülleriniz için önerilenler: stilleri ve polyfill'leri ayrı giriş noktalarına çıkarın, saf yardımcı programları (yan etkisi olmayan fonksiyonlar) yan etkileri olan modüllerden (başlatma, günlükleme, Service Worker kaydı) ayırın. Üst düzey proje package.json'da, yalnızca tüm modüller safsa "sideEffects": false belirtin. Stiller varsa, tam olarak "sideEffects": ["*.css"] belirtin.
{
"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"] şu anlama gelir: tüm CSS dosyalarının yan etkileri vardır (kaldırılamazlar) ve polyfills.js'nin de vardır. Paketteki diğer tüm JS dosyaları saftır — güvenle shake edilebilirler. module alanı, bundler'ın Tree Shaking için CommonJS sürümü (main) yerine kullanması gereken paketin ES sürümünün yolunu belirtir.
React Native, Metro Bundler ile sınırlı bir Tree Shaking sürümünü destekler. Metro, Webpack gibi kullanılan exportların (usedExports) tam statik analizini yapmaz. Bunun yerine Metro, küçültme sırasında modüllerin kullanılmayan kısımlarını kaldırmak için Terser'a güvenir. Bu yaklaşımın etkinliği, Webpack'teki tam Tree Shaking'ten daha düşüktür.
React Native projelerinin maksimum optimizasyonu için önerilenler: ES modüllü kütüphaneler kullanın (package.json'daki module alanı), hata ayıklama kodunu kaldırmak için babel-plugin-transform-remove-console ekleyin ve Terser için Metro transformer.minifierConfig'i yapılandırın. Ek olarak, Ram Bundle (bundle'ı modüllere bölme) kullanılmayan ekranların yüklenmesini azaltır.
Sıkça Sorulan Sorular
CommonJS (require/module.exports) statik analizi desteklemez — require, koşullar ve fonksiyonlar içinde dinamik olarak çağrılabilir. Bundler, modülün hangi bölümlerinin gerçekten kullanıldığını belirleyemez. Yalnızca statik import/export'a sahip ES modülleri Tree Shaking'e izin verir.
TypeScript, tsconfig.json'un ES modülleri için yapılandırılması koşuluyla ("module": "esnext") Tree Shaking ile tamamen uyumludur. TypeScript derleyicisi, import/export'u CommonJS'ye dönüştürmeden korumalıdır. @babel/preset-typescript ve modules: false ile Babel de ES modüllerini Webpack'e doğru şekilde iletir.
Webpack Bundle Analyzer, bundle bileşimini etkileşimli bir diyagram olarak görselleştiren bir eklentidir. Bir kütüphane bundle'da mevcutsa ancak fonksiyonları kullanılmıyorsa, Tree Shaking çalışmamıştır. Çıktı dosyasını da analiz edebilirsiniz: grep aracılığıyla bundle metninde kullanılmayan exportları arayın.
Lodash v4, CommonJS paketi olarak dağıtılır. Tree Shaking için lodash-es — kütüphanenin ES sürümünü kullanmanız gerekir. import throttle from "lodash/throttle" ifadesini import { throttle } from "lodash-es" ile değiştirin ve lodash'ı lodash-es ile değiştirmek için Webpack'te resolve.alias'ı yapılandırın.
Tree Shaking, bağımlılık grafiği analizi ve kullanılan exportları işaretleme aşamasını eklediği için derleme süresini biraz artırır (%5–15). Geliştirme modunda Tree Shaking genellikle hız için devre dışı bırakılır. Üre timde, ek süre bundle boyutundaki önemli azalmayla haklı çıkarılır.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun