Олег Марков
Tree shaking в JavaScript - как работает и как правильно настроить
Введение
Tree shaking в современном фронтенд-разработке стал одним из ключевых инструментов оптимизации. Эта техника позволяет удалить из финального бандла весь код, который фактически нигде не используется. В результате снижается вес JavaScript-файлов, ускоряется загрузка приложения и уменьшается время выполнения.
Давайте разберем, что именно такое Tree shaking, почему он появился именно с модулями ES6, как он работает внутри сборщиков и что нужно делать вам, чтобы он действительно приносил пользу, а не существовал только на слайдах из презентаций.
Вы увидите практические примеры конфигураций для Webpack, Rollup и ESBuild, а также реальные кейсы: почему иногда Tree shaking “не срабатывает”, как правильно писать код и публиковать библиотеки, чтобы оптимизация проходила максимально агрессивно.
Что такое Tree shaking и откуда взялся термин
Интуитивное объяснение
Представьте дерево: ствол, ветки и листья. При сборке JavaScript-приложения все ваши файлы, модули и функции образуют условное “дерево зависимостей”. Когда вы импортируете что-то из модуля, сборщик считает, что эта часть кода “нужна” и оставляет ее. Остальные, неиспользуемые части могут быть “стряхнуты” с дерева, как сухие листья.
Смотрите, что происходит на практике:
- у вас есть модуль с десятью функциями;
- вы импортируете только одну из них;
- сборщик с поддержкой Tree shaking оставляет только эту функцию, а остальные девять удаляет из финального бандла.
Почему Tree shaking связан с ES-модулями
Ключевой момент: Tree shaking корректно работает только с “статическим анализом” кода. Это означает, что сборщик должен заранее, на этапе сборки, понять:
- какие функции где объявлены;
- какие из них точно импортируются;
- какие экспорты точно не используются.
С модулями CommonJS (require, module.exports) это сделать сложно, потому что импорты и экспорты могут быть динамическими, зависящими от условий, и сборщик не может гарантировать их структуру.
ES-модули (import и export) устроены по-другому:
- структура импортов и экспортов статична;
- имена привязаны на этапе компиляции;
- нельзя динамически изменить, что именно экспортируется.
Благодаря этому сборщик может построить точный граф зависимостей и “стряхнуть” все, что не используется.
Мертвая кодовая ветка против Tree shaking
Иногда путают Tree shaking и удаление “мертвого кода” (dead code elimination). Разница такая:
- Dead code elimination — это оптимизация на уровне JavaScript-движка или минификатора. Она удаляет код, который точно не будет выполнен (например, ветку if (false) { ... }).
- Tree shaking — удаляет неиспользуемые экспорты модулей, даже если они теоретически могли бы выполниться, если бы были импортированы.
Обычно Tree shaking и dead code elimination работают вместе. Сначала сборщик отмечает неиспользуемые экспорты, затем минификатор удаляет связанные с ними участки кода.
Основные принципы работы Tree shaking
Статический анализ импортов и экспортов
Давайте посмотрим на простой пример:
// math.js
export function add(a, b) {
// Здесь мы складываем два числа
return a + b
}
export function multiply(a, b) {
// Здесь мы перемножаем два числа
return a * b
}
// index.js
import { add } from './math.js'
// Здесь мы используем только функцию add
console.log(add(2, 3))
Если сборщик поддерживает Tree shaking и правильно настроен, в итоговый бандл попадет только функция add. Функция multiply будет удалена, потому что:
- она экспортируется;
- но нигде не импортируется;
- значит, она “мертвая” с точки зрения графа зависимостей.
Важно: если бы вы импортировали весь модуль целиком, ситуация была бы другой.
// Плохой для Tree shaking вариант
import * as math from './math.js'
console.log(math.add(2, 3))
Многие сборщики в таком случае “перестрахуются” и оставят весь код модуля math.js, потому что не всегда могут доказать, что вы не будете использовать math.multiply где-то еще.
Side effects и почему они ломают Tree shaking
Один из главных врагов Tree shaking — побочные эффекты (side effects). Побочный эффект — это любой код, который что-то меняет вне своей области, даже если результат не присваивается никуда напрямую. Примеры:
- модуль при импорте что-то логирует в консоль;
- модуль изменяет глобальный объект window;
- модуль регистрирует что-то в глобальном реестре.
Смотрите на пример:
// logger.js
console.log('Логгер инициализирован') // Побочный эффект
export function log(message) {
// Здесь мы выводим сообщение в консоль
console.log(message)
}
// index.js
// Здесь мы нигде не используем log, но просто импортируем модуль
import './logger.js'
Даже если вы нигде не вызываете log, сам импорт logger.js нужен, потому что важен побочный эффект — вывод “Логгер инициализирован”. Сборщик не имеет права удалить этот импорт.
Отсюда два важных вывода:
- Если модуль имеет побочные эффекты, его нельзя “стряхнуть” целиком.
- Если вы используете стороннюю библиотеку, в которой инкапсулированы побочные эффекты, Tree shaking для нее может быть сильно ограничен.
Marking sideEffects: false и consequences
Многие сборщики позволяют разработчику явно сказать: “мой пакет не имеет побочных эффектов при импорте” или “побочные эффекты только в определенных файлах”. Это делается через поле sideEffects в package.json.
Например:
{
"name": "my-lib",
"version": "1.0.0",
"module": "dist/index.esm.js",
"sideEffects": false
}
Комментарий к этому примеру:
// sideEffects: false говорит сборщику - при импорте этого пакета // никакого кода с побочными эффектами не выполняется // значит, можно безопасно удалять неиспользуемые импорты
Если вы нарушите это обещание (у вас есть модуль, который что-то выполняет при импорте), а при этом указали sideEffects: false, то сборщик может удалить нужный код, и вы получите баг в рантайме.
Поэтому:
- если вы пишете библиотеку, убедитесь, что действительно нет побочных эффектов при импорте, прежде чем ставить sideEffects: false;
- если побочные эффекты есть только в отдельных файлах, укажите это явно с помощью массива путей.
{
"sideEffects": [
"./src/polyfills.js",
"./src/styles.css"
]
}
Комментарий:
// В этом случае сборщик может смело удалять почти все файлы // кроме тех, что перечислены в sideEffects // Они всегда должны оставаться, даже если импорты выглядят "неиспользуемыми"
Tree shaking в Webpack
Базовые условия, чтобы Tree shaking заработал
Чтобы Webpack вообще смог применять Tree shaking, должны выполняться несколько условий:
- Вы используете ES-модули (import и export).
- В конфигурации установлен режим production (или включена оптимизация вручную).
- Код минифицируется с помощью Terser или другого минификатора, который умеет удалять неиспользуемый код.
- Правильно настроено поле sideEffects для пакетов.
Простейший пример конфигурации:
// webpack.config.js
const path = require('path')
module.exports = {
mode: 'production', // В продакшн-режиме Webpack включает оптимизации
entry: './src/index.js',
output: {
filename: 'bundle.js',
// Здесь мы указываем папку для сборки
path: path.resolve(__dirname, 'dist')
},
optimization: {
usedExports: true, // Помечает используемые экспорты
// В режиме production Webpack автоматически включает minimizer с Terser
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
// Здесь мы подключаем Babel для транспиляции
use: 'babel-loader'
}
]
}
}
В mode: 'production' опция usedExports включается автоматически, но здесь я указываю ее явно, чтобы вам было понятнее, что именно отвечает за Tree shaking.
Пример: как Webpack удаляет неиспользуемый код
Давайте разберем минимальный пример.
// src/utils.js
export function needed() {
// Эта функция нужна и будет использоваться
return 'I am used'
}
export function notNeeded() {
// Эта функция никогда не будет импортирована
return 'I am unused'
}
// src/index.js
import { needed } from './utils.js'
console.log(needed()) // Выводим результат в консоль
Если вы соберете этот проект в режиме production, Webpack:
- отметит экспорт needed как используемый;
- отметит экспорт notNeeded как неиспользуемый;
- при минификации Terser удалит код notNeeded.
Если вы откроете минифицированный bundle.js (желательно через source map), вы увидите, что функция notNeeded туда не попала.
Как sideEffects влияет на Webpack
Представьте, что у вас в проекте есть index.js, который просто переэкспортирует другие модули:
// src/index.js
export * from './buttons.js'
export * from './inputs.js'
export * from './modals.js'
Даже если вы в своем приложении используете только одну кнопку из buttons.js, Webpack может “подстраховаться” и включить в бандл код всех трех файлов, если он не уверен, есть ли у них побочные эффекты.
Чтобы Webpack мог более агрессивно встряхивать дерево экспорта, ему нужно знать, что ваши модули не содержат побочных эффектов. Для этого вы добавляете в package.json:
{
"sideEffects": false
}
Комментарий:
// Теперь Webpack может смело удалять целые файлы, если их экспорты // не используются нигде в коде
Если же побочные эффекты есть только в отдельных модулях, вы указываете их в массиве:
{
"sideEffects": [
"./src/polyfills.js",
"./src/global.css"
]
}
Webpack при этом:
- никогда не удалит импорты polyfills.js и global.css;
- будет свободно удалять остальные “модульные” файлы, если их экспорты не используются.
Типичные ошибки при Tree shaking в Webpack
Разберем несколько ситуаций, когда вы ожидаете Tree shaking, а он не срабатывает.
Ошибка 1. Использование require вместо import
// Плохой вариант
const utils = require('./utils')
// Здесь Webpack теряет статическую информацию об экспортах
console.log(utils.needed())
В этом случае Webpack не может безопасно “стряхнуть” неиспользуемые функции из utils, потому что require работает динамически. Вы можете позже обратиться к utils.notNeeded, и сборщик об этом не узнает.
Решение:
// Хороший вариант
import { needed } from './utils.js'
console.log(needed())
Ошибка 2. Динамические импорты с переменной
// Плохой вариант
const moduleName = './utils'
import(moduleName).then(mod => {
// Что именно здесь будет использоваться - сборщик не знает
console.log(mod)
})
Сборщику сложно анализировать такой код. Лучше использовать явные пути:
// Лучше
import('./utils.js').then(mod => {
// Здесь хотя бы понятно, какой модуль именно загружается
console.log(mod.needed())
})
Ошибка 3. Babel ломает модули
Если Babel перенастроен так, что он преобразует ES-модули в CommonJS (использует @babel/preset-env с modules: 'commonjs' или без указания modules в некоторых конфигурациях), то на выходе для Webpack модули уже не статические ES-модули.
Пример правильной конфигурации Babel:
{
"presets": [
[
"@babel/preset-env",
{
"modules": false // Важно - оставляем ES-модули для сборщика
}
]
]
}
Комментарий:
// modules: false говорит Babel - не трогай import и export // пусть ими занимается Webpack или другой сборщик
Если вы забудете про modules: false, Babel превратит import в require, и Webpack потеряет возможность нормально делать Tree shaking.
Tree shaking в Rollup
Почему Rollup считается “эталоном” Tree shaking
Rollup изначально проектировался именно как модульный бандлер с фокусом на Tree shaking. В отличие от Webpack, который долгое время поддерживал CommonJS и множество форматов, Rollup делает ставку на ES-модули и работает с ними очень агрессивно.
В результате:
- Rollup может удалять не только неиспользуемые функции, но и “расползающийся” код внутри модулей;
- он аккуратно анализирует побочные эффекты;
- бандлы получаются очень компактными, особенно для библиотек.
Минимальная конфигурация Rollup с Tree shaking
Давайте посмотрим простой пример.
// rollup.config.js
import { defineConfig } from 'rollup'
import babel from '@rollup/plugin-babel'
export default defineConfig({
input: 'src/index.js', // Точка входа
output: {
file: 'dist/bundle.js',
format: 'esm' // Формат выхода - ES-модули
},
plugins: [
babel({
babelHelpers: 'bundled',
// Здесь мы указываем Babel использовать наш .babelrc или настройки
exclude: 'node_modules/**'
})
],
treeshake: {
moduleSideEffects: false
// moduleSideEffects позволяет указать, что модули без явных побочных эффектов
// можно обрезать максимально агрессивно
}
})
По умолчанию Rollup уже включает Tree shaking. Опция treeshake позволяет контролировать его поведение тоньше:
- treeshake: true — включить Tree shaking;
- moduleSideEffects: false — считать, что модули не имеют побочных эффектов (аналог sideEffects: false, но на уровне конфигурации Rollup);
- либо можно указывать функции и паттерны.
Пример, как Rollup удаляет неиспользуемые части
Давайте разберем модуль, где внутри функции есть “мертвые” части:
// src/math.js
export function compute(x) {
// Здесь мы рассчитываем значение x * 2
const result = x * 2
// Этот блок никогда не будет выполнен
if (false) {
console.log('Этот код никогда не выполнится')
}
return result
}
// src/index.js
import { compute } from './math.js'
console.log(compute(10))
Rollup:
- Анализирует модуль math.js.
- Понимает, что if (false) — мертвая ветка.
- Удаляет ее даже до стадии минификации.
Минификатор затем еще сильнее оптимизирует код, но уже получает “очищенную” версию.
moduleSideEffects и точный контроль
Иногда в проекте встречаются модули с побочными эффектами в виде вызовов, которые вы хотите контролировать. Rollup позволяет указать moduleSideEffects как:
- false — считать, что модуль не имеет побочных эффектов;
- true — всегда считать, что побочные эффекты есть;
- массив или функцию — для тонкой настройки.
Пример:
// rollup.config.js (фрагмент)
export default {
// ...
treeshake: {
moduleSideEffects: id => {
// Здесь id - путь к модулю
// Укажем, что только polyfills.js имеет побочные эффекты
if (id.endsWith('polyfills.js')) {
return true
}
return false
}
}
}
Комментарий:
// Такая настройка позволяет вам явно пометить модули с побочными эффектами // и максимально встряхивать все остальные
Rollup как инструмент для библиотек
Если вы пишете библиотеку, которая будет устанавливаться через npm, Rollup часто оказывается удобнее Webpack:
- он генерирует чистый ESM или UMD;
- Tree shaking работает “из коробки”;
- можно сделать несколько форматов (cjs, esm) в одном конфиге.
Пример настройки выходов:
// rollup.config.js (фрагмент)
export default {
input: 'src/index.js',
output: [
{
file: 'dist/index.cjs',
format: 'cjs' // CommonJS для Node.js
},
{
file: 'dist/index.esm.js',
format: 'esm' // ES-модули для Tree shaking в сборщиках
}
]
}
Комментарий:
// Так вы публикуете сразу два формата // Пользователи браузерных сборщиков будут использовать ESM // и смогут получать все преимущества Tree shaking
Tree shaking в ESBuild
Особенности ESBuild
ESBuild — это очень быстрый сборщик и транспайлер, написанный на Go. Он поддерживает Tree shaking, но делает это несколько иначе, чем Webpack и Rollup:
- он по умолчанию предполагает, что код может содержать побочные эффекты;
- чтобы Tree shaking работал агрессивно, нужно включать формат ESM и режим bundling;
- ESBuild учитывает поле sideEffects в package.json.
Пример базовой конфигурации через CLI:
esbuild src/index.js \
--bundle \
--format=esm \
--minify \
--outfile=dist/bundle.js
Комментарий:
// --bundle - собираем все модули в один файл // --format=esm - оставляем формат ES-модулей // --minify - включаем минификацию и удаление неиспользуемого кода
Пример с Tree shaking в ESBuild
Давайте разберем следующий код:
// src/helpers.js
export function used() {
// Эта функция используется в коде
return 'used'
}
export function unused() {
// Эта функция нигде не вызывается
return 'unused'
}
// src/index.js
import { used } from './helpers.js'
console.log(used())
При сборке с ESBuild:
- экспорт used останется;
- экспорт unused будет удален из итогового бандла (если нет побочных эффектов в модуле).
Учет поля sideEffects ESBuild
ESBuild, как и Webpack, читает поле sideEffects в package.json, чтобы понять, можно ли удалять импорты, которые кажутся неиспользуемыми.
Если у вас есть пакет с:
{
"sideEffects": false
}
то ESBuild может удалять даже “голые” импорты без использования, если считает, что побочных эффектов там нет.
Например:
import './polyfills.js' // Если sideEffects: false, ESBuild может удалить этот импорт
Чтобы этого не произошло, если в polyfills.js действительно есть побочные эффекты, вам нужно:
- либо не ставить sideEffects: false;
- либо явно указать polyfills.js в массиве sideEffects.
{
"sideEffects": [
"./src/polyfills.js"
]
}
Комментарий:
// Так вы защищаете критичный модуль с полифилами от удаления // даже если его импорт выглядит "неиспользуемым" в коде
Как писать код, который хорошо “стряхивается”
Используйте только ES-модули
Главное правило: пишите модули с использованием import и export. Избегайте:
- require;
- module.exports;
- динамических import с переменными путями.
Правильные примеры:
// utils.js
export function formatDate(date) {
// Здесь мы форматируем дату в строку
return date.toISOString()
}
export function parseDate(str) {
// Здесь мы разбираем строку в объект Date
return new Date(str)
}
// main.js
import { formatDate } from './utils.js'
const now = new Date()
// Здесь мы выводим отформатированную дату
console.log(formatDate(now))
При таком подходе Tree shaking может спокойно удалить parseDate, если она нигде не используется.
Избегайте “собирающих” модулей без необходимости
Часто разработчики создают index.js, который переэкспортирует все подряд:
// components/index.js
export * from './Button.js'
export * from './Input.js'
export * from './Modal.js'
export * from './Dropdown.js'
А затем в приложении:
// main.js
import { Button } from './components/index.js'
Смотрите, что происходит: сборщику может быть сложнее понять, какие модули действительно нужны, особенно если есть побочные эффекты. Лучше, когда возможно, импортировать компоненты напрямую:
// Рекомендация для максимального Tree shaking
import { Button } from './components/Button.js'
или
import Button from './components/Button.js'
Тогда сборщик точно знает, что индексный модуль components/index.js вообще не нужен, и может его выкинуть.
Не смешивайте побочные эффекты и чистые функции
Хорошая практика — разделять модули:
- на чистые, без побочных эффектов, которые содержат только функции и классы;
- и на модули инициализации, которые что-то делают при импорте (инициализируют глобальные слушатели, регистрируют плагины).
Пример:
// analytics/core.js
export function trackEvent(name, payload) {
// Здесь мы отправляем событие аналитики на сервер
console.log('Send event', name, payload)
}
// analytics/init.js
import { trackEvent } from './core.js'
// Здесь мы регистрируем обработчик кликов
document.addEventListener('click', event => {
trackEvent('click', { x: event.clientX, y: event.clientY })
})
Если вы хотите Tree shaking только для analytics/core.js, а init.js должен всегда выполняться при явном импорте, вы можете:
- указать init.js в sideEffects;
- а core.js оставить “чистым” и пригодным для Tree shaking.
{
"sideEffects": [
"./src/analytics/init.js"
]
}
Комментарий:
// Теперь импорты из core.js будут анализироваться и обрезаться // а init.js будет всегда считаться модулем с побочными эффектами
Избегайте “скрытых” побочных эффектов
Иногда внутри функций вы можете делать что-то, что сложно предсказать сборщику:
- изменять глобальные переменные;
- модифицировать прототипы встроенных объектов;
- регистрировать что-то в глобальных синглтонах.
С точки зрения Tree shaking это не всегда критично, но такие практики ухудшают прогнозируемость кода. Если сборщик не может точно сказать, влияют ли эти операции на остальную часть программы, он будет консервативнее в оптимизациях.
Лучше:
- делать функции чистыми, где это возможно;
- побочные эффекты помещать в явно помеченные “инициализационные” модули.
Tree shaking и публикация библиотек
Как правильно готовить библиотеку к Tree shaking
Когда вы публикуете библиотеку в npm и хотите, чтобы пользователи могли “стряхивать” неиспользуемые части:
- Обязательно предоставляйте сборку в формате ES-модулей.
- Указывайте поле module в package.json.
- Настраивайте sideEffects.
Пример package.json:
{
"name": "awesome-lib",
"version": "1.0.0",
"main": "dist/index.cjs", // CommonJS-версия для Node.js
"module": "dist/index.esm.js", // ESM-версия для Tree shaking
"sideEffects": false
}
Комментарий:
// main - точка входа для окружений, ожидающих CommonJS // module - точка входа для сборщиков, которые умеют Tree shaking // sideEffects: false - библиотека не выполняет побочных эффектов при импорте
Если побочные эффекты есть только в определенных местах (например, у вас есть глобальная инициализация), укажите их явно.
{
"sideEffects": [
"./dist/polyfills.js",
"./dist/registerGlobal.js"
]
}
Структура экспорта для лучшего Tree shaking
Старайтесь экспортировать ваши функции, классы и компоненты “поштучно”, а не одним огромным объектом.
Меньше подходит:
// index.esm.js
const lib = {
a() {
// ...
},
b() {
// ...
}
}
export default lib
Сборщику сложно удалить отдельные свойства объекта lib, потому что они могут использоваться динамически.
Лучше:
// index.esm.js
export function a() {
// ...
}
export function b() {
// ...
}
Теперь пользователь может написать:
import { a } from 'awesome-lib'
// Здесь будет импортирована только функция a
a()
И Tree shaking удалит функцию b, если она не используется.
Избегайте “магических” индексных файлов
Часто для удобства делают:
// src/index.js
import './polyfills.js' // Побочный эффект при импорте
export * from './core.js'
Если вы укажете module: "dist/index.esm.js" и sideEffects: false, то пользователь, который импортирует всего одну функцию из вашей библиотеки, неожиданно получит полифилы, которые вы не планировали “вешать” автоматически.
Лучший подход:
- разделить index с полифилами и index без полифилов;
- либо вынести полифилы в отдельный модуль, который пользователь импортирует явно.
// src/index.js
export * from './core.js'
// src/with-polyfills.js
import './polyfills.js'
export * from './core.js'
Тогда в package.json вы укажете:
{
"module": "dist/index.esm.js",
"exports": {
".": "./dist/index.esm.js",
"./with-polyfills": "./dist/with-polyfills.esm.js"
}
}
Комментарий:
// Пользователь сам решает, нужен ли ему вариант с полифилами // А основной вход остается "чистым" и хорошо поддающимся Tree shaking
Заключение
Tree shaking — это не одна волшебная галочка в конфигурации сборщика, а результат совместной работы:
- архитектуры модулей в вашем коде;
- формата экспорта библиотек;
- настройки сборщика (Webpack, Rollup, ESBuild);
- корректного описания побочных эффектов через sideEffects и аналогичные опции.
Если вы:
- используете ES-модули;
- избегаете лишних побочных эффектов в модулях;
- правильно настраиваете Babel (modules: false);
- аккуратно описываете sideEffects в package.json,
то Tree shaking начинает работать заметно лучше: размер бандла уменьшается, загрузка приложения ускоряется, а пользователи загружают только тот код, который им действительно нужен.
Полезно периодически проверять итоговые бандлы с помощью инструментов анализа (webpack-bundle-analyzer, source-map-explorer и аналогичных). Так вы на практике увидите, какие модули “не стряхиваются” и почему, и сможете шаг за шагом улучшать структуру кода.
Частозадаваемые технические вопросы по теме Tree shaking
Как понять, что Tree shaking действительно сработал в моем проекте
- Соберите проект в режиме production.
- Подключите анализатор бандла:
- для Webpack используйте webpack-bundle-analyzer;
- для других сборщиков можно использовать source-map-explorer.
- Посмотрите, попадают ли в бандл модули и функции, которые вы ожидаете удалить.
- Если неиспользуемый код остался, проверьте:
- используете ли вы ES-модули;
- не ломает ли Babel формат модулей;
- как настроено поле sideEffects.
Почему при использовании TypeScript Tree shaking иногда не работает
- Проверьте компилятор TypeScript:
- в tsconfig.json установите "module": "ESNext" или "ES2015";
- избегайте "module": "CommonJS".
- Убедитесь, что сборщик (Webpack, Rollup, ESBuild) обрабатывает уже ESM-код, а не CommonJS.
- Если используете ts-loader или babel-loader, посмотрите, не преобразуют ли они модули в CommonJS.
Можно ли добиться Tree shaking с CommonJS модулями
Полноценного Tree shaking для CommonJS добиться нельзя, но можно частично:
- Некоторые сборщики пытаются делать “lazy evaluation”, но это нестабильно.
- Рекомендуется постепенно переписывать модули на ES-модули.
- Если библиотека только в CommonJS, попробуйте найти ESM-версию или форк.
Как быть с CSS и Tree shaking
- CSS сам по себе не поддается Tree shaking так же, как JS.
- Некоторые инструменты (например, PurgeCSS, Tailwind JIT) реализуют “аналог” Tree shaking для стилей:
- анализируют HTML и JS;
- удаляют неиспользуемые классы из итогового CSS.
- Для Webpack можно подключать плагины, удаляющие неиспользуемые правила стилей на основе анализа разметки.
Почему импорт по умолчанию мешает Tree shaking как экспорта по частям
- При default export часто делают “объект с кучей методов”:
- сборщику сложно удалить отдельные свойства такого объекта.
- Лучше экспортировать функции поименно:
- export function a() {}
- export function b() {}
- Импортировать тоже поименно:
- import { a } from 'lib' Тогда сборщик увидит, что b не используется, и удалит ее.
Постройте личный план изучения Vue до уровня Middle — бесплатно!
Vue — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по Vue
Лучшие курсы по теме

Vue 3 и Pinia
Антон Ларичев
TypeScript с нуля
Антон Ларичев