Tree shaking

Tree shaking — это процесс удаления неиспользуемого кода из конечного бандла. Основная цель — уменьшение размера JavaScript-файлов и повышение производительности веб-приложений. Tree shaking особенно актуален при работе с современными библиотеками, где модульность позволяет импортировать только необходимые функции, минимизируя лишний код.

Принципы работы

Tree shaking работает на уровне ES6-модулей. Основные механизмы:

  • Статический анализ импорта/экспорта. Компилятор или сборщик проверяет, какие экспорты действительно используются в проекте.
  • Удаление неиспользуемого кода. Любые функции, классы или переменные, которые не импортируются или не вызываются, исключаются из итогового бандла.
  • Поддержка «side effect free» модулей. Чтобы tree shaking корректно работал, модули не должны иметь побочные эффекты при импорте. Например, выполнение кода при подключении модуля без явного вызова функций считается побочным эффектом.

Требования к эффективному tree shaking

  1. Использование ES6 import/export вместо CommonJS (require/module.exports).

    // Правильно
    import { map, filter } from 'umbrella';
    
    // Неправильно
    const u = require('umbrella');
  2. Отсутствие побочных эффектов в модулях. Для библиотек, таких как Umbrella JS, важно, чтобы импорт функции не вызывал скрытые действия (например, изменение глобальных переменных).

  3. Настройка сборщика (Webpack, Rollup, Vite) для анализа tree shaking:

    • mode: 'production' в Webpack активирует минификацию и dead code elimination.
    • Rollup и Vite используют ES модули по умолчанию, что делает tree shaking более точным.

Tree shaking в Umbrella JS

Umbrella JS — небольшая, модульная библиотека для работы с DOM. Каждая функция экспортируется отдельно, что делает её идеальной для tree shaking. Например, при импорте только метода u.find остальной код библиотеки может быть исключен из бандла.

// Импорт конкретной функции
import u from 'umbrella-js';

// Используем только find
const items = u('div').find('.active');

В этом случае сборщик может исключить методы hide, show, addClass и другие, если они не используются.

Стратегии оптимизации кода

  • Именованные импорты. Позволяют точно указать, какие функции нужны:

    import { find, addClass } from 'umbrella';

    Такой подход упрощает анализ для сборщика и повышает эффективность tree shaking.

  • Разделение кода (code splitting). Даже при modular import рекомендуется делить проект на чанки, чтобы загружать только необходимые части библиотеки на каждой странице.

  • Минимизация и Uglify. Инструменты типа Terser автоматически удаляют неиспользуемые объявления и функции, если сборщик правильно отметил их как dead code.

Ограничения и подводные камни

  1. Побочные эффекты. Если модуль изменяет глобальное состояние при импорте, сборщик не может удалить его полностью без риска нарушения логики приложения.

  2. Динамические импорты. Tree shaking не применим к require() или import() с переменной:

    const method = 'find';
    u(method)('div'); // этот код не поддается tree shaking
  3. Неименованные экспорты по умолчанию. Экспорт по умолчанию затрудняет статический анализ, поэтому именованные экспорты предпочтительнее:

    export function hide() { ... }
    export function show() { ... }

Инструменты для проверки

  • Webpack Bundle Analyzer. Визуализирует размер бандла и показывает, какие модули остаются после tree shaking.
  • Rollup. Отчет о tree shaking через флаг treeshake: true.
  • Vite. Использует Rollup под капотом, автоматически активирует оптимизацию ES модулей.

Примеры практического использования

  1. Импорт только функций, необходимых для взаимодействия с DOM:
import { find, addClass } from 'umbrella';

u('ul li').addClass('highlight');
  1. Избегание глобальных вызовов и side effect:
// Плохо
import 'umbrella-js/dist/umbrella.js'; // весь код подключается

// Хорошо
import { hide, show } from 'umbrella';

Эти практики позволяют уменьшить бандл на десятки килобайт, особенно в проектах с большим количеством страниц и функций.


Tree shaking в сочетании с модульной архитектурой Umbrella JS обеспечивает компактность, ускоряет загрузку страниц и снижает нагрузку на браузер. Правильное использование ES6-импортов и внимательное отношение к побочным эффектам модулей является ключом к эффективной оптимизации.