Tree Shaking: co to je, mechanismus odstraňování mrtvého kódu a nástroje

Autor: IT Sectr Publikováno: 2026-05-18 Doba čtení: 8 min

Tree Shaking — mechanismus odstraňování nepoužívaného kódu (dead code elimination) ve fázi sestavování aplikace. Tree Shaking analyzuje statickou strukturu ES-modulů a vylučuje exportované funkce, třídy a proměnné, které nejsou nikde importovány. Podle Webpack Documentation může správná konfigurace Tree Shaking zmenšit velikost bundle o 30–60% bez změny funkcionality aplikace.

Hlavní body

  • Tree Shaking — odstraňování nepoužívaných exportů z ES-modulů na základě statické analýzy import/export
  • ES-moduly (import/export) — jediný formát podporující Tree Shaking; CommonJS není podporován
  • Webpack a Rollup — hlavní nástroje pro sestavování s podporou Tree Shaking přes pluginy
  • Side effects — vedlejší efekty v modulech blokují Tree Shaking; příznak sideEffects: false v package.json řeší problém
  • Used exports — analýza použití exportů v production režimu Webpack pro přesné odstranění mrtvého kódu

Co je Tree Shaking?

Tree Shaking (třesení stromem) — technika optimalizace kódu, při které jsou z finálního bundle vyloučeny moduly a funkce nepoužívané v aplikaci. Termín byl zaveden týmem Rollup v roce 2015 a metaforicky popisuje proces: strom závislostí se zatřese a nepoužívané větve odpadnou. Na rozdíl od ruční optimalizace se Tree Shaking provádí automaticky ve fázi sestavování.

Tree Shaking funguje pouze s ES-moduly (ECMAScript Modules), kde jsou závislosti definovány staticky pomocí import a export. CommonJS (require/module.exports) nepodporuje Tree Shaking, protože require se provádí dynamicky — nástroj pro sestavování nemůže předem určit, které funkce jsou skutečně používány. Moderní knihovny (Lodash, Moment.js, RxJS) vydávají ES verze pro podporu Tree Shaking.

Rollup: průkopník Tree Shaking

Rollup — první nástroj pro sestavování, který implementoval Tree Shaking v roce 2015. Na rozdíl od Webpack byl Rollup od začátku navržen pro ES-moduly a provádí agresivnější odstraňování mrtvého kódu. Rollup analyzuje nejen jednotlivé exporty, ale i celé moduly: pokud modul nemá vedlejší efekty a žádný export není používán, Rollup vyloučí celý modul z bundle.

Rollup je obzvláště účinný pro knihovny a SDK, kde každý kilobajt hraje roli. Framework Vue.js používá Rollup pro sestavení produkční verze. React přešel na Rollup v roce 2020. Pro aplikace se častěji používá Webpack kvůli bohatšímu ekosystému pluginů (Hot Module Replacement, code splitting, CSS modules), ale pro maximální Tree Shaking při sestavování knihoven zůstává Rollup průmyslovým standardem.

Úspora z Tree Shaking silně závisí na architektuře projektu. V aplikaci React s knihovnou Ant Design může Tree Shaking odstranit až 70% kódu UI komponent. V projektu, kde jsou všechny importy specifické a přesné, bude úspora 5–15%. Průměrná úspora podle výzkumů Webpack je 30–40% velikosti bundle.

Co je mrtvý kód

Typ mrtvého kóduPříkladDetekce Tree Shaking
Nepoužívaný exportexport function unusedHelper()Ano
Nepoužívaný importimport { unused } from "lib"Ano
Mrtvá větev podmínkyif (false) { ... }Ne (odstraní minifikátor)
Nevolaná funkce po DCEfunction a(){} a() kde a není volánaČástečně

Jak funguje Tree Shaking: statická analýza modulů

Mechanismus Tree Shaking je založen na grafu závislostí (dependency graph), který nástroj pro sestavování vytvoří ze všech import/export v projektu. V první fázi nástroj projde všechny soubory od vstupního bodu (entry point) a shromáždí strom modulů. Ve druhé fázi se analyzuje, které exporty z každého modulu jsou skutečně importovány v jiných modulech.

Pro každý modul Webpack nebo Rollup označí exporty jako používané nebo nepoužívané. Nepoužívané exporty jsou z bundle vyloučeny. Samotný modul však v bundle zůstává, pokud je používán alespoň jeden jeho export. Úplné vyloučení modulu je možné pouze přes příznak sideEffects nebo pokud modul neobsahuje žádné vedlejší efekty.

Příklad: před a po Tree Shaking

js
// utils.js — modul s funkcemi
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 — vstupní bod
import { formatDate } from "./utils";

const today = formatDate(new Date());
console.log(today);
js
// Po Tree Shaking — v bundle pouze formatDate
function formatDate(date) {
  return date.toISOString().slice(0, 10);
}
const today = formatDate(new Date());
console.log(today);

Tree Shaking vyloučil formatCurrency a slugify z finálního bundle, protože nejsou importovány v app.js. Velikost modulu utils.js se zmenšila ze 3 funkcí na 1. Pokud utils.js obsahuje side effects (např. globální inicializaci), Tree Shaking nebude moci odstranit ani nepoužívané exporty.

Tree Shaking v Webpack: konfigurace a optimalizace

Webpack obsahuje vestavěnou podporu pro Tree Shaking přes plugin TerserPlugin v production režimu. Pro zapnutí Tree Shaking stačí dvě podmínky: mode nastaven na production (mode: "production") a moduly používající ES syntaxi (import/export). Webpack automaticky označí nepoužívané exporty a předá je Terser k odstranění.

Další konfigurace usedExports: true v optimization.webpack.config.js zapne podrobnou analýzu použití exportů uvnitř modulu. Tato volba určuje, které exporty jsou skutečně používány (used) a které jsou pouze exportovány (provided). Kombinace usedExports a Terser poskytuje maximální účinnost odstraňování mrtvého kódu.

Konfigurace Webpack pro Tree Shaking

js
// webpack.config.js — konfigurace 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 }],
            ],
          },
        },
      },
    ],
  },
};

Klíčový parametr — modules: false v @babel/preset-env. Babel ve výchozím nastavení převádí ES-moduly na CommonJS, což zabíjí Tree Shaking. modules: false zakáže Babel převádět import/export a zachovává ES syntaxi pro Webpack. concatenateModules navíc spojuje moduly do společného rozsahu viditelnosti, čímž snižuje počet IIFE a velikost bundle.

Problém side effects a příznak sideEffects

Side effects (vedlejší efekty) — akce modulu při jeho importu, které nesouvisejí s exportovanými hodnotami: globální styly (import "./styles.css"), polyfilly (import "core-js/stable"), inicializace globálních proměnných nebo registrace Service Worker. Pokud modul obsahuje side effects, nástroj pro sestavování jej nemůže bezpečně odstranit z bundle, i když není používán žádný export.

Příznak sideEffects v package.json informuje nástroj pro sestavování, které moduly v balíčku nemají vedlejší efekty. Pro balíček, kde jsou všechny moduly čisté (pouze export funkcí), je třeba nastavit "sideEffects": false. Pro balíčky s CSS nebo polyfilly — pole cest k souborům s vedlejšími efekty: "sideEffects": ["*.css"]. Bez tohoto příznaku Tree Shaking neodstraní ani nepoužívané funkce.

Jak určit side effects ve vlastním kódu

Chcete-li zjistit, zda má modul vedlejší efekty, položte otázku: provede tento import nějaké akce nesouvisející s exportem hodnot? import "./styles.css" přidává CSS do DOM — to je side effect. import { throttle } from "lodash-es" nemá side effects — pouze zpřístupňuje funkci throttle. Polyfilly (import "core-js/stable") mají side effects — mění globální prototypy.

Pro vlastní moduly se doporučuje: přesunout styly a polyfilly do samostatných vstupních bodů, oddělit čisté nástroje (funkce bez side effects) od modulů s vedlejšími efekty (inicializace, logování, registrace Service Worker). V package.json projektu nejvyšší úrovně nastavte "sideEffects": false pouze pokud jsou všechny moduly čisté. Pokud existují styly — nastavte "sideEffects": ["*.css"] přesně.

Příklad konfigurace 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"] znamená: všechny CSS soubory mají vedlejší efekty (nelze je odstranit) a polyfills.js také. Všechny ostatní JS soubory v balíčku jsou čisté — lze je bezpečně shake-ovat. Pole module ukazuje cestu k ES verzi balíčku, kterou má nástroj pro sestavování použít místo CommonJS verze (main) pro Tree Shaking.

Tree Shaking v React Native a Metro

React Native s Metro Bundler podporuje omezenou verzi Tree Shaking. Metro neprovádí úplnou statickou analýzu používaných exportů (usedExports) jako Webpack. Místo toho se Metro spoléhá na Terser pro odstranění nepoužívané části modulů ve fázi minifikace. Účinnost tohoto přístupu je nižší než plný Tree Shaking v Webpack.

Pro maximální optimalizaci projektů React Native se doporučuje: používat knihovny s ES-moduly (pole module v package.json), připojit pluginy babel-plugin-transform-remove-console pro odstranění ladícího kódu a nakonfigurovat Metro transformer.minifierConfig pro Terser. Dále Ram Bundle (rozdělení bundle na moduly) snižuje načítání nepoužívaných obrazovek.

Často kladené otázky

Proč Tree Shaking nefunguje s CommonJS?

CommonJS (require/module.exports) nepodporuje statickou analýzu — require může být volán dynamicky uvnitř podmínek a funkcí. Nástroj pro sestavování nemůže určit, které části modulu jsou skutečně používány. Pouze ES-moduly se statickými import/export umožňují Tree Shaking.

Lze použít Tree Shaking s TypeScript?

TypeScript je plně kompatibilní s Tree Shaking za předpokladu, že tsconfig.json je nakonfigurován pro ES-moduly: "module": "esnext". TypeScript kompilátor musí zachovat import/export bez převodu na CommonJS. Babel s @babel/preset-typescript a modules: false také správně předává ES-moduly do Webpack.

Jak zkontrolovat, zda Tree Shaking fungoval?

Webpack Bundle Analyzer — plugin vizualizující složení bundle jako interaktivní diagram. Pokud je knihovna přítomna v bundle, ale její funkce nejsou používány, Tree Shaking nefungoval. Lze také analyzovat výstupní soubor: najít nepoužívaný export v textu bundle přes grep.

Proč Lodash není tree-shake-ován ve výchozím nastavení?

Lodash v4 je distribuován jako CommonJS balíček. Pro Tree Shaking je třeba použít lodash-es — ES verzi knihovny. Nahraďte import throttle from "lodash/throttle" za import { throttle } from "lodash-es" a nakonfigurujte resolve.alias v Webpack pro nahrazení lodash za lodash-es.

Ovlivňuje Tree Shaking dobu sestavování?

Tree Shaking mírně zvyšuje dobu sestavování (o 5–15%), protože přidává fázi analýzy grafu závislostí a označování používaných exportů. V development režimu je Tree Shaking obvykle vypnut kvůli rychlosti. V production je dodatečný čas vyvážen výrazným zmenšením velikosti bundle.

Shrnutí

  • Tree Shaking — automatické odstraňování nepoužívaných ES exportů ve fázi sestavování, zmenšení velikosti bundle o 30–60%
  • ES-moduly — jediný formát podporující statickou analýzu; CommonJS není vhodný pro Tree Shaking
  • Webpack a Rollup zajišťují Tree Shaking přes usedExports a Terser v production režimu
  • Side effects blokují odstranění modulu; příznak sideEffects: false v package.json řeší problém pro čisté knihovny
  • Babel musí být nakonfigurován s modules: false, aby nepřeváděl ES-moduly na CommonJS
  • React Native Metro má omezený Tree Shaking, spoléhající se na Terser ve fázi minifikace

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také