Прямой ответ
Разделение кода распределяет приложение на части, загружаемые по мере необходимости. Удаление неиспользуемого кода исключает из сборки функции, которые не вызываются.
| Механизм | Что сокращает |
|---|---|
| Разделение кода | Объём первоначальной загрузки |
| Удаление неиспользуемого | Объём каждой части |
| Минификация | Размер передаваемого файла |
// Динамический импорт создаёт отдельную часть
const Settings = () => import('./Settings.vue')
// Статический импорт включается в текущую часть
import { formatDate } from './utils'
Динамический импорт определяет границу части: код, доступный через динамический импорт, выносится в отдельный файл, который загружается при первом обращении.
Удаление неиспользуемого кода работает с модулями, структура которых известна на этапе сборки. О составе сборки — в статье про размер бандла.
Границы частей и требования к модулям
Два аспекта определяют эффективность разделения и удаления кода.
Границы частей. Часть создаётся по динамическому импорту, поэтому группировка кода определяет, что загружается вместе. Часть, содержащая rarely используемый код, загружается целиком при первом обращении к любому её элементу.
Требования к модулям. Удаление неиспользуемого кода опирается на статическую структуру импортов. Модуль, который изменяет глобальное состояние при загрузке, не может быть исключён, поскольку побочный эффект выполняется независимо от использования экспортов.
Практическое следствие: объявление побочных эффектов модуля в манифесте пакета позволяет сборщику исключить неиспользуемые модули.
Отдельный аспект — общий код. Модуль, используемый несколькими частями, либо дублируется в каждой, либо выносится в общую часть. Дублирование увеличивает общий объём, общая часть добавляет запрос при загрузке.
Три признака неэффективного разделения.
Одна часть на всё приложение. Первоначальная загрузка включает код, который не нужен сразу, поэтому время загрузки растёт.
Слишком много малых частей. Каждая часть требует отдельного запроса, поэтому накладные расходы на запросы превышают выигрыш.
Дублирование общего кода. Один модуль включён в несколько частей, поэтому общий объём передачи растёт.
О настройке сборщика — в статье про сборку фронтенда; об отложенной загрузке компонентов — в статье про ленивую загрузку.
Проверка состава сборки выполняется анализом частей, поскольку фактический состав может отличаться от ожидаемого.
Практика: настройка разделения и удаления кода
1. Определите границы частей по маршрутам и компонентам. Код, не нужный сразу, выносится в отдельную часть.
2. Используйте динамический импорт для отложенных частей. Граница части определяется местом динамического импорта.
3. Объявляйте побочные эффекты модулей. Модуль без побочных эффектов может быть исключён, если его экспорты не используются.
4. Выносите общий код в отдельную часть. Дублирование модуля в нескольких частях увеличивает общий объём.
5. Проверяйте состав сборки. Анализ частей показывает фактический состав, а не предполагаемый.
6. Не создавайте слишком много малых частей. Каждая часть требует отдельного запроса, поэтому накладные расходы растут.
7. Пересматривайте границы при изменении приложения. Изменение состава компонентов делает прежние границы неоптимальными.
Рекомендации:
- Различайте разделение кода и отложенную загрузку. Разделение определяет состав частей, отложенная загрузка — момент получения части.
- Учитывайте число запросов. Каждая часть требует отдельного запроса, поэтому избыточное дробление увеличивает накладные расходы.
- Проверяйте удаление неиспользуемого кода. Модуль с побочными эффектами не исключается, поэтому состав сборки проверяется.
- Фиксируйте границы частей в конфигурации. Изменение границ влияет на объём частей и число запросов.
- Пересматривайте при добавлении зависимостей. Новая зависимость может увеличить объём части, поэтому состав проверяется после изменения.
Практический сценарий: первоначальная загрузка включала весь код приложения
Контекст: время загрузки страницы было высоким, поскольку браузер получал весь код приложения сразу.
- Диагностика. Анализ сборки показал одну часть, содержащую код всех маршрутов и компонентов. Код, не нужный для первого экрана, загружался вместе с остальным.
- Причина. Границы частей не были определены, поэтому весь код собирался в один файл. Отложенная загрузка компонентов не использовалась.
- Действия. (а) Определили границы частей по маршрутам, чтобы код каждого маршрута загружался при переходе; (б) применили динамический импорт для компонентов, не нужных на первом экране; (в) объявили побочные эффекты модулей, чтобы неиспользуемые исключались; (г) вынесли общий код в отдельную часть, чтобы не дублировать его; (д) проверили состав сборки после изменения и убедились в сокращении первоначальной части.
- Результат. Объём первоначальной загрузки сократился, поскольку код других маршрутов загружается при переходе.
Вывод: без определённых границ частей весь код приложения загружается сразу. Разделение по маршрутам и динамический импорт сокращают объём первоначальной загрузки.
FAQ
Что определяет границу части? Динамический импорт. Код, доступный через динамический импорт, выносится в отдельный файл, загружаемый при первом обращении.
Почему неиспользуемый код не удаляется? Модуль с побочными эффектами не может быть исключён, поскольку эффект выполняется независимо от использования экспортов. Объявление отсутствия побочных эффектов позволяет исключить модуль.
Сколько частей оптимально? Определяется балансом между объёмом первоначальной загрузки и числом запросов. Избыточное дробление увеличивает накладные расходы на запросы.
Как проверить состав сборки? Анализом частей, который показывает фактический состав файлов. Предполагаемый состав может отличаться от фактического.
Источники: Vite guide, MDN import, Rollup introduction — ссылки в шапке.