Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Як працює "tree shaking"?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Tree shaking** - це процес аналізу імпортів/експортів модулів і видалення тих, які не використовуються у фінальному коді. **Ключове:** якщо функція, клас чи змінна ніколи не викликається чи не імпортується, збирач просто викидає їх з підсумкового бандла.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що таке Tree Shaking **Tree shaking** - це процес аналізу імпортів/експортів модулів і **видалення тих, які не використовуються** у фінальному коді. Простіше кажучи: > Якщо функція, клас чи змінна **ніколи не викликається / не імпортується**, збирач просто викидає їх з підсумкового бандла. Назва метафорична: дерево = граф залежностей проєкту, shaking = «струшуємо» невикористані гілки. --- ## Приклад без tree shaking ```javascript // math.js export function add(a, b) { return a + b; } export function multiply(a, b) { return a * b; } // app.js import { add } from './math.js'; console.log(add(2, 3)); ``` Без tree shaking у бандл потрапить **і** `add`**, і** `multiply`, хоча `multiply` не використовується. --- ## Приклад з tree shaking Сучасний збирач (Rollup, Webpack 5+, ESBuild, Vite) проаналізує: - `multiply` ніде не імпортується, - отже, можна безпечно видалити. У підсумковому бандлі залишиться лише: ```javascript function add(a,b){return a+b} console.log(add(2,3)) ``` --- ## Умови, щоб tree shaking спрацював Tree shaking працює **лише з ES Modules (ESM)**, тому що вони **статичні**: ```javascript // ESM import { add } from './math.js'; // CommonJS (аналіз неможливий на етапі збирання) const math = require('./math'); ``` Збирач має бачити всі імпорти/експорти **на етапі компіляції**, а не під час виконання (динамічні require() ламають оптимізацію). --- ## Як збирач розуміє, що можна видалити Tree shaking - це **аналіз графа залежностей**: 1. Визначає "корені" - модулі, реально використовувані в застосунку (entry points); 2. Будує граф імпортів; 3. Видаляє все, що недосяжне з цих коренів. --- ## "Dead Code Elimination" vs "Tree Shaking" Tree shaking - логічний аналіз **імпортів/експортів** на рівні модулів. Dead code elimination (DCE) - подальший **аналіз на рівні виразів** (зазвичай робить Terser/UglifyJS). Зазвичай ланцюжок такий: ```javascript Webpack / Rollup → позначають невикористані експорти ↓ Terser → фізично вирізає код ``` --- ## Приклад: побічні ефекти (side effects) Tree shaking **не видаляє код з побічними ефектами** - те, що може змінити глобальний стан. ```javascript // utils.js console.log('модуль завантажено'); // побічний ефект! export const a = 1; export const b = 2; ``` Навіть якщо ти не імпортуєш `a` чи `b`, збирач **не видалить** модуль, якщо бачить побічний ефект (виклик `console.log`, зміну глобальної змінної тощо). --- ## Підказка збирачу: `package.json → sideEffects` У пакетах можна явно вказати, що код **без побічних ефектів**, тоді tree shaking працює агресивніше: ```javascript { "name": "my-lib", "sideEffects": false } ``` або вибірково: ```javascript { "sideEffects": [ "*.css", "./polyfills.js" ] } ``` --- ## Типові проблеми, через які tree shaking не працює | Причина | Чому | |---|---| | Використовується CommonJS (`require`) | немає статичного аналізу залежностей | | Динамічні імпорти (`import * as m`) або `require(variable)` | збирач не може передбачити, що саме імпортується | | Побічні ефекти в модулях | їх не можна безпечно видалити | | Плагіни або транспіляція ламають ESM | наприклад, Babel перетворює `import/export` на `require` | | Не увімкнено `mode: 'production'` у Webpack | у dev-режимі оптимізації вимкнені | --- ## Приклад: Webpack ```javascript // webpack.config.js module.exports = { mode: 'production', // вмикає tree-shaking + minify optimization: { usedExports: true, // позначає використані експорти } }; ``` Якщо ти дивишся в bundle-analyzer, побачиш коментарі `/* unused harmony export */` - це tree shaking у дії. --- ## Приклад: Rollup (ідеальний випадок) Rollup спочатку був побудований навколо tree shaking, тому він робить це найкраще: ```javascript // rollup.config.js export default { input: 'src/index.js', output: { file: 'dist/bundle.js', format: 'esm' } }; ``` Rollup видаляє невикористані експорти і навіть "ланцюжки" функцій, якщо вони не викликаються. --- ## Інтеграція з Vite / ESBuild Vite і ESBuild **завжди** працюють з ESM і **вбудовано** підтримують tree shaking - нічого налаштовувати не потрібно. Головне: не використовувати CommonJS і не мати прихованих побічних ефектів. --- ## Підсумок | Що | Опис | |---|---| | **Tree shaking** | Видалення невикористаних імпортів/експортів | | **Працює лише з** | ES Modules (`import` / `export`) | | **Не видаляє** | Код з побічними ефектами | | **Налаштування** | `sideEffects: false` у `package.json`, `mode: production` | | **Інструменти** | Webpack ≥ 2, Rollup, ESBuild, Vite | | **Мета** | Зменшити розмір бандла без ручного видалення коду | --- **Головна ідея:** > Збирач будує "дерево залежностей" і "струшує" з нього все, > що не використовується, тому "tree shaking".Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.