Tree Shaking — mechanisme voor het verwijderen van ongebruikte code (dead code elimination) tijdens de build-fase van de applicatie. Tree Shaking analyseert de statische structuur van ES-modules en sluit geëxporteerde functies, klassen en variabelen uit die nergens worden geïmporteerd. Volgens Webpack Documentation kan een correcte configuratie van Tree Shaking de bundelgrootte met 30–60% verminderen zonder de functionaliteit van de applicatie te wijzigen.
Belangrijkste
Tree Shaking (het schudden van de boom) — een code-optimalisatietechniek waarbij modules en functies die niet in de applicatie worden gebruikt, uit de uiteindelijke bundel worden verwijderd. De term werd in 2015 geïntroduceerd door het Rollup-team en beschrijft metaforisch het proces: de afhankelijkheidsboom wordt geschud en ongebruikte takken vallen eraf. In tegenstelling tot handmatige optimalisatie wordt Tree Shaking automatisch uitgevoerd tijdens de build-fase.
Tree Shaking werkt alleen met ES-modules (ECMAScript Modules), waar afhankelijkheden statisch worden gedefinieerd via import en export. CommonJS (require/module.exports) ondersteunt Tree Shaking niet, omdat require dynamisch wordt uitgevoerd — de bundelaar kan niet van tevoren bepalen welke functies echt worden gebruikt. Moderne bibliotheken (Lodash, Moment.js, RxJS) brengen ES-versies uit voor ondersteuning van Tree Shaking.
Rollup — de eerste bundelaar die Tree Shaking in 2015 implementeerde. In tegenstelling tot Webpack is Rollup vanaf het begin ontworpen voor ES-modules en voert het een agressievere verwijdering van dode code uit. Rollup analyseert niet alleen individuele exporten, maar ook hele modules: als een module geen bijwerkingen heeft en geen export wordt gebruikt, sluit Rollup de hele module uit van de bundel.
Rollup is bijzonder effectief voor bibliotheken en SDK's, waar elke kilobyte telt. Het Vue.js-framework gebruikt Rollup voor het bouwen van de productieversie. React stapte in 2020 over op Rollup. Voor applicaties wordt vaker Webpack gebruikt vanwege het rijkere plugin-ecosysteem (Hot Module Replacement, code splitting, CSS modules), maar voor maximale Tree Shaking bij het bouwen van bibliotheken blijft Rollup de industriestandaard.
De besparing van Tree Shaking hangt sterk af van de projectarchitectuur. In een React-applicatie met de Ant Design-bibliotheek kan Tree Shaking tot 70% van de code van UI-componenten verwijderen. In een project waar alle imports specifiek en punctueel zijn, zal de besparing 5–15% bedragen. De gemiddelde besparing volgens Webpack-onderzoeken is 30–40% van de bundelgrootte.
| Type dode code | Voorbeeld | Detectie door Tree Shaking |
|---|---|---|
| Ongebruikte export | export function unusedHelper() | Ja |
| Ongebruikte import | import { unused } from "lib" | Ja |
| Dode tak van conditie | if (false) { ... } | Nee (verwijderd door minificator) |
| Niet-aangeroepen functie na DCE | function a(){} a() waar a niet wordt aangeroepen | Gedeeltelijk |
Het mechanisme van Tree Shaking is gebaseerd op de afhankelijkheidsgraaf (dependency graph) die de bundelaar opbouwt uit alle import/export in het project. In de eerste fase doorloopt de bundelaar alle bestanden vanaf het startpunt (entry point) en verzamelt de boom van modules. In de tweede fase wordt geanalyseerd welke exporten uit elke module daadwerkelijk in andere modules worden geïmporteerd.
Voor elke module markeert Webpack of Rollup exporten als gebruikt of ongebruikt. Ongebruikte exporten worden uit de bundel verwijderd. De module zelf blijft echter in de bundel als ten minste één export wordt gebruikt. Een module volledig uitsluiten kan alleen via de sideEffects-vlag of als de module geen bijwerkingen bevat.
// utils.js — module met functies
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 — startpunt
import { formatDate } from "./utils";
const today = formatDate(new Date());
console.log(today);// Na Tree Shaking — in de bundel alleen formatDate
function formatDate(date) {
return date.toISOString().slice(0, 10);
}
const today = formatDate(new Date());
console.log(today);Tree Shaking heeft formatCurrency en slugify uit de uiteindelijke bundel verwijderd omdat ze niet worden geïmporteerd in app.js. De grootte van de module utils.js is van 3 functies naar 1 verminderd. Als utils.js side effects bevat (bijvoorbeeld globale initialisatie), kan Tree Shaking zelfs ongebruikte exporten niet verwijderen.
Webpack bevat ingebouwde ondersteuning voor Tree Shaking via de TerserPlugin in de productiemodus. Voor het inschakelen van Tree Shaking zijn twee voorwaarden voldoende: mode ingesteld op production (mode: "production") en modules die ES-syntax (import/export) gebruiken. Webpack markeert automatisch ongebruikte exporten en stuurt ze naar Terser voor verwijdering.
Extra configuratie usedExports: true in optimization.webpack.config.js schakelt gedetailleerde analyse van het gebruik van exporten binnen de module in. Deze optie bepaalt welke exporten daadwerkelijk worden gebruikt (used) en welke alleen worden geëxporteerd (provided). De combinatie van usedExports en Terser geeft maximale efficiëntie bij het verwijderen van dode code.
// webpack.config.js — Tree Shaking configuratie
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 }],
],
},
},
},
],
},
};De belangrijkste parameter — modules: false in @babel/preset-env. Babel converteert standaard ES-modules naar CommonJS, wat Tree Shaking doodt. modules: false verbiedt Babel om import/export te converteren en behoudt de ES-syntax voor Webpack. concatenateModules combineert bovendien modules in een gemeenschappelijk bereik, waardoor het aantal IIFE's en de bundelgrootte afnemen.
Side effects (bijwerkingen) — acties van een module bij het importeren die niet gerelateerd zijn aan geëxporteerde waarden: globale stijlen (import "./styles.css"), polyfills (import "core-js/stable"), initialisatie van globale variabelen of registratie van Service Worker. Als een module side effects bevat, kan de bundelaar deze niet veilig uit de bundel verwijderen, zelfs als geen enkele export wordt gebruikt.
De sideEffects-vlag in package.json informeert de bundelaar welke modules in het pakket geen bijwerkingen hebben. Voor een pakket waarin alle modules zuiver zijn (alleen functie-export), moet "sideEffects": false worden ingesteld. Voor pakketten met CSS of polyfills — een array van paden naar bestanden met bijwerkingen: "sideEffects": ["*.css"]. Zonder deze vlag zal Tree Shaking zelfs ongebruikte functies niet verwijderen.
Om te controleren of een module bijwerkingen heeft, stel de vraag: zal deze import acties uitvoeren die geen verband houden met de export van waarden? import "./styles.css" voegt CSS toe aan de DOM — dit is een side effect. import { throttle } from "lodash-es" heeft geen side effects — het maakt alleen de functie throttle beschikbaar. Polyfills (import "core-js/stable") hebben side effects — ze wijzigen globale prototypen.
Voor eigen modules wordt aanbevolen: stijlen en polyfills naar afzonderlijke entry points verplaatsen, zuivere hulpprogramma's (functies zonder side effects) scheiden van modules met bijwerkingen (initialisatie, logging, Service Worker-registratie). In package.json van het bovenliggende project "sideEffects": false alleen instellen als alle modules zuiver zijn. Als er stijlen zijn — "sideEffects": ["*.css"] nauwkeurig instellen.
{
"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"] betekent: alle CSS-bestanden hebben bijwerkingen (ze kunnen niet worden verwijderd) en polyfills.js ook. Alle andere JS-bestanden in het pakket zijn zuiver — ze kunnen veilig worden geschud. Het veld module geeft het pad naar de ES-versie van het pakket aan die de bundelaar moet gebruiken in plaats van de CommonJS-versie (main) voor Tree Shaking.
React Native met Metro Bundler ondersteunt een beperkte versie van Tree Shaking. Metro voert geen volledige statische analyse van gebruikte exporten (usedExports) uit zoals Webpack. In plaats daarvan vertrouwt Metro op Terser voor het verwijderen van ongebruikte delen van modules tijdens de minificatiefase. De efficiëntie van deze aanpak is lager dan volledige Tree Shaking in Webpack.
Voor maximale optimalisatie van React Native projecten wordt aanbevolen: bibliotheken met ES-modules gebruiken (veld module in package.json), plugins babel-plugin-transform-remove-console aansluiten voor het verwijderen van debug-code en Metro transformer.minifierConfig configureren voor Terser. Daarnaast vermindert Ram Bundle (splitsing van de bundel in modules) het laden van ongebruikte schermen.
Veelgestelde vragen
CommonJS (require/module.exports) ondersteunt geen statische analyse — require kan dynamisch worden aangeroepen binnen voorwaarden en functies. De bundelaar kan niet bepalen welke delen van de module daadwerkelijk worden gebruikt. Alleen ES-modules met statische import/export maken Tree Shaking mogelijk.
TypeScript is volledig compatibel met Tree Shaking op voorwaarde dat tsconfig.json is geconfigureerd voor ES-modules: "module": "esnext". De TypeScript-compiler moet import/export behouden zonder conversie naar CommonJS. Babel met @babel/preset-typescript en modules: false geeft ES-modules ook correct door aan Webpack.
Webpack Bundle Analyzer — een plugin die de samenstelling van de bundel visualiseert als een interactief diagram. Als een bibliotheek aanwezig is in de bundel maar de functies niet worden gebruikt, heeft Tree Shaking niet gewerkt. Ook kan het uitvoerbestand worden geanalyseerd: zoek een ongebruikte export in de bundeltekst via grep.
Lodash v4 wordt gedistribueerd als CommonJS-pakket. Voor Tree Shaking moet lodash-es worden gebruikt — de ES-versie van de bibliotheek. Vervang import throttle from "lodash/throttle" door import { throttle } from "lodash-es" en configureer resolve.alias in Webpack om lodash te vervangen door lodash-es.
Tree Shaking verhoogt de bouwtijd licht (met 5–15%), omdat het een fase van analyse van de afhankelijkheidsgraaf en het markeren van gebruikte exporten toevoegt. In de development-modus is Tree Shaking meestal uitgeschakeld voor snelheid. In productie wordt de extra tijd gerechtvaardigd door de aanzienlijke vermindering van de bundelgrootte.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook