Перейти к содержимому

7. Tree Shaking

Tree shaking (встряхивание дерева) — это процесс удаления неиспользуемого кода из финального бандла. Название метафорично: представьте дерево зависимостей, которое встряхивают, и мёртвые (неиспользуемые) ветки-модули опадают.

Tree shaking основан на статическом анализе import/export ES модулей. Webpack строит граф зависимостей и помечает код как “используемый” или “мёртвый”.

// math.js — библиотека функций
export const add = (a, b) => a + b; // ✅ используется
export const subtract = (a, b) => a - b; // ❌ мёртвый код
export const multiply = (a, b) => a * b; // ❌ мёртвый код
export const divide = (a, b) => a / b; // ❌ мёртвый код
// app.js — использует только add
import { add } from './math';
console.log(add(1, 2));

После tree shaking в бандл попадёт только add. subtract, multiply, divide будут удалены.

Tree shaking не работает с CommonJS! Только ES модули (import/export) поддаются статическому анализу:

// ❌ CommonJS — tree shaking не работает
const { add } = require('./math');
module.exports = { add, subtract };
// ✅ ESM — tree shaking работает
import { add } from './math';
export { add };
module.exports = {
mode: 'production', // Включает TerserPlugin, который удаляет мёртвый код
};
// .babelrc — важно!
{
"presets": [
["@babel/preset-env", {
"modules": false // ← Не компилировать import/export → require()
}]
]
}

Чтобы Webpack знал, какие файлы можно безопасно удалить, укажите sideEffects:

package.json
{
"name": "my-library",
"sideEffects": false // Весь код без побочных эффектов — можно удалять
}
// Если некоторые файлы имеют side effects (CSS, polyfills):
{
"sideEffects": [
"*.css", // CSS файлы нельзя удалять
"./src/polyfills.js",
"./src/setup.js"
]
}

Что считается side effect:

  • Изменение глобальных переменных: window.MyLib = ...
  • Полифиллы: Array.prototype.includes = ...
  • Автоматически выполняемый код при импорте
  • CSS файлы (изменяют стили)

Что не является side effect:

  • Чистые функции
  • Классы и типы
  • Константы
Окно терминала
# Анализ бандла — что попало в итоговый файл?
npx webpack-bundle-analyzer dist/stats.json
# Генерация stats.json
npx webpack --json > dist/stats.json
// ❌ Импортирует ВСЮ lodash (70 KB)
import _ from 'lodash';
const result = _.debounce(fn, 300);
// ✅ Импортирует только debounce (2 KB)
import debounce from 'lodash/debounce';
// или
import { debounce } from 'lodash-es'; // ESM версия lodash
// Material UI — правильный импорт
// ❌ import { Button } from '@mui/material'; // может импортировать всё
// ✅ import Button from '@mui/material/Button'; // только Button
optimization: {
usedExports: true, // Помечает неиспользуемые экспорты
minimize: true, // Удаляет помеченный код (через Terser)
concatenateModules: true, // Scope hoisting — объединяет модули
}

Ниже — интерактивная демонстрация tree shaking. Импортируйте разные функции и смотрите что попадёт в бандл.