Tree shaking
Tree shaking це процес видалення невикористаного коду з фінального JavaScript-бандла. Назва дослівно означає «струшування дерева»: уявіть, що код проєкту це дерево, а зайві, мертві гілки (функції, модулі, імпорти) просто відпадають під час збірки. Менше коду означає швидше завантаження і кращу продуктивність.
Теорія
TL;DR
- Якщо функція, змінна або імпорт ніде не використовуються, збирач (Webpack, Rollup, Vite) видалить цей код з підсумкового файлу.
- Тримається на ES Modules:
import/exportстатичні, тому їх можна проаналізувати на етапі збірки. - CommonJS (
require) tree shaking не підтримує. - Побічні ефекти блокують видалення модуля, доки
package.jsonне скаже"sideEffects": false. - У Rollup, Vite та esbuild працює з коробки, у Webpack вмикається в production-режимі.
Швидкий приклад
// utils.js
export function add(a, b) { return a + b; }
export function sub(a, b) { return a - b; }
export function mul(a, b) { return a * b; }
export function div(a, b) { return a / b; }
// main.js
import { add } from './utils.js';
console.log(add(2, 3));Без tree shaking збирач покладе в bundle.js усі функції (add, sub, mul, div), навіть якщо реально використовується лише add(). З увімкненим tree shaking (production-режим Webpack, Rollup або Vite) у підсумковому бандлі залишиться тільки add(). У результаті розмір бандла менший, завантаження швидше, а парсинг і виконання коду теж швидші.
Як це працює технічно
Tree shaking спирається на три речі:
- ES Modules (ESM), тобто
import/export: на відміну відrequire, ESM-імпорти статичні й аналізуються на етапі збірки; - статичний аналіз залежностей: збирач знає, які саме експорти реально використовуються;
- видалення мертвого коду через оптимізацію dead code elimination.
// імпорт статичний, тому збирач бачить, що використовується лише add
import { add } from './utils.js';А от CommonJS не підтримує tree shaking:
const utils = require('./utils'); // збирач не може точно знати, що використовуєтьсяКоли tree shaking не спрацює
Tree shaking не працює, якщо:
- ви використовуєте CommonJS (
require) замість ES Modules (import/export); - код має побічні ефекти, наприклад виконується під час імпорту;
- бібліотека не вказала
"sideEffects": falseуpackage.json; - ви пишете динамічні імпорти або звертаєтеся до властивостей через змінні.
Приклад із побічним ефектом:
// side.js
console.log("This code runs on import!");
export const x = 42;Навіть якщо x не використовується, весь файл не буде видалено, бо під час імпорту виконується console.log(), а це побічний ефект.
Налаштування у Webpack, Rollup і Vite
Webpack. Tree shaking вмикається автоматично в production-режимі, якщо в package.json є:
{
"sideEffects": false
}Замість false можна дати список файлів, у яких побічні ефекти справді є.
Rollup. Tree shaking увімкнений за замовчуванням. Історично Rollup був першим збирачем, який це впровадив.
Vite та esbuild. Працює з коробки, бо обидва побудовані навколо ESM, а Vite ще й використовує Rollup для production-збірки.
Приклад результату
До оптимізації бандл важив 120 KB, після tree shaking, 42 KB.
| Пункт | Опис |
|---|---|
| Що робить | Видаляє невикористаний код з підсумкового бандла |
| На чому базується | ESM (import / export) і статичний аналіз |
| Працює в | Webpack, Rollup, Vite, Parcel |
| Не працює з | require(), побічними ефектами |
| Мета | Зменшити розмір і пришвидшити завантаження |
Типові помилки
- Чекати tree shaking від CommonJS-залежності. Якщо бібліотека публікує лише CJS-збірку, збирач не зможе нічого відрізати; шукайте пакет з полем
moduleабоexportsна ESM. - Імпортувати весь пакет заради однієї функції.
import _ from 'lodash'тягне все;import debounce from 'lodash-es/debounce'дає збирачу шанс. - Ставити
"sideEffects": falseнаосліп. Якщо у пакеті є файли з реальними побічними ефектами, наприклад глобальні поліфіли або імпорт CSS, вони мовчки зникнуть з бандла. - Перевіряти результат у dev-режимі. У Webpack tree shaking працює лише в production-збірці, тож розмір треба міряти саме на ній.
- Звертатися до експортів через змінну.
utils[name]()робить статичний аналіз неможливим, і збирач залишає все. - Плутати tree shaking з мініфікацією. Мініфікатор скорочує наявний код, а tree shaking взагалі не дає невикористаному коду потрапити в бандл.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.