Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Tree shaking». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Tree shaking це видалення невикористаного коду з фінального JavaScript-бандла.** Збирач (Webpack, Rollup, Vite, Parcel) статично аналізує граф `import` / `export`, бачить, які експорти ніде не використовуються, і викидає їх, тобто робить dead code elimination. Працює це лише на ES Modules: `require()` з CommonJS проаналізувати статично не можна, а модуль із побічними ефектами збирач не наважиться видалити, якщо в `package.json` немає `"sideEffects": false`. **Ключове:** менший бандл означає не лише швидше завантаження, а й швидший парсинг і виконання коду.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**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-режимі. ### Швидкий приклад ```javascript // 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 спирається на три речі: 1. **ES Modules (ESM)**, тобто `import` / `export`: на відміну від `require`, ESM-імпорти статичні й аналізуються на етапі збірки; 2. **статичний аналіз залежностей**: збирач знає, які саме експорти реально використовуються; 3. **видалення мертвого коду** через оптимізацію dead code elimination. ```javascript // імпорт статичний, тому збирач бачить, що використовується лише add import { add } from './utils.js'; ``` А от CommonJS не підтримує tree shaking: ```javascript const utils = require('./utils'); // збирач не може точно знати, що використовується ``` ### Коли tree shaking не спрацює Tree shaking не працює, якщо: - ви використовуєте CommonJS (`require`) замість ES Modules (`import` / `export`); - код має побічні ефекти, наприклад виконується під час імпорту; - бібліотека не вказала `"sideEffects": false` у `package.json`; - ви пишете динамічні імпорти або звертаєтеся до властивостей через змінні. Приклад із побічним ефектом: ```javascript // 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` є: ```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 взагалі не дає невикористаному коду потрапити в бандл.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.