Предварительное объединение зависимостей
Когда вы запускаете vite
в первый раз, Vite предварительно собирает зависимости вашего проекта перед локальной загрузкой сайта. По умолчанию это происходит автоматически и прозрачно.
Зачем?
Так Vite выполняет то, что мы называем «предварительным объединением зависимостей». Этот процесс служит двум целям:
Совместимость CommonJS и UMD: во время разработки сборщик Vite использует весь код как собственный ESM. Поэтому Vite должен сначала преобразовать зависимости, поставляемые как CommonJS или UMD, в ESM.
При преобразовании зависимостей CommonJS Vite выполняет интеллектуальный анализ импорта, чтобы именованный импорт в модули CommonJS работал должным образом, даже если экспорт назначается динамически (например, React):
js// работает как ожидалось import React, { useState } from 'react'
Производительность: Vite преобразует зависимости ESM со многими внутренними модулями в один модуль, чтобы улучшить последующую производительность загрузки страниц.
Некоторые пакеты поставляют свои сборки ES-модулей в виде множества отдельных файлов, импортирующих друг друга. Например,
lodash-es
имеет более 600 внутренних модулей! Когда мы делаемimport { debounce } из 'lodash-es'
, браузер выполняет 600+ HTTP-запросов одновременно! Несмотря на то что сервер без проблем справляется с ними, большое количество запросов создает перегрузку сети на стороне браузера, из-за чего страница загружается заметно медленнее.Благодаря предварительному объединению
lodash-es
в один модуль нам теперь нужен только один HTTP-запрос!
ПРИМЕЧАНИЕ
Предварительное объединение зависимостей применяется только в режиме разработки и использует esbuild
для преобразования зависимостей в ESM. В продакшен-сборках вместо этого используется @rollup/plugin-commonjs
.
Автоматическое обнаружение зависимостей
Если существующий кэш не найден, Vite просмотрит ваш исходный код и автоматически обнаружит импорт зависимостей (т. е. «голый импорт» которые должны быть разрешены из node_modules
) и использовать эти найденные импорты в качестве точек входа для предварительного пакета. Предварительное пакетирование выполняется с помощью esbuild
, поэтому оно обычно происходит очень быстро.
После запуска сервера, если встречается новый импорт зависимостей, которого ещё нет в кэше, Vite повторно запускает процесс объединения зависимостей и при необходимости перезагружает страницу.
Монорепы и связанные зависимости
При настройке монорепозитория зависимостью может быть связанный пакет из того же репозитория. Vite автоматически обнаруживает зависимости, которые не разрешены с помощью node_modules
, и обрабатывает связанный пакет как исходный код. Он не будет пытаться объединить связанную зависимость, а вместо этого проанализирует список зависимостей этой связанной зависимости.
Однако для этого необходимо экспортировать связанную зависимость в формате ESM. Для этого можно добавить требуемый пакет в optimizeDeps.include
и build.commonjsOptions.include
в вашем конфиге.
export default defineConfig({
optimizeDeps: {
include: ['linked-dep'],
},
build: {
commonjsOptions: {
include: [/linked-dep/, /node_modules/],
},
},
})
При внесении изменений в код связанного пакета перезапустите dev-сервер с опцией командной строки --force
, чтобы изменения вступили в силу.
Настройка поведения
Эвристика обнаружения зависимостей по умолчанию не всегда может быть желательной. В случаях, когда вы хотите явно включить/исключить зависимости из списка, используйте параметр optimizeDeps
.
Типичный случай использования optimizeDeps.include
или optimizeDeps.exclude
— когда у вас есть импорт, который нельзя напрямую обнаружить в исходном коде. Например, импорт может быть создан в результате преобразования плагина. Это означает, что Vite не сможет обнаружить импорт при первом сканировании — он сможет обнаружить его только после того, как файл будет запрошен браузером и преобразован. Это приведёт к тому, что после запуска сервера он будет немедленно пересобираться.
Для решения этой проблемы можно использовать как include
, так и exclude
. Если зависимость большая (с большим количеством внутренних модулей) или является CommonJS, то её следует включить. Если зависимость небольшая и уже является валидным ESM, вы можете исключить её и позволить браузеру загружать её напрямую.
Вы также можете дополнительно настроить esbuild с помощью опции optimizeDeps.esbuildOptions
. Например, добавив плагин esbuild для обработки специальных файлов в зависимостях, или изменив параметр target
в секции build
.
Кэширование
Кэш файловой системы
Vite кэширует предварительно объединённые зависимости в node_modules/.vite
. Он определяет необходимость повторного выполнения этапа предварительного пакетирования на основе нескольких источников:
- Содержимое файла блокировки менеджера пакетов, например
package-lock.json
,yarn.lock
,pnpm-lock.yaml
илиbun.lockb
. - Время модификации папки.
- Соответствующие поля в вашем файле
vite.config.js
, если они есть. - Значение
NODE_ENV
.
Шаг предварительной комплектации нужно будет повторно выполнить только в том случае, если одно из вышеперечисленных условий изменилось.
Если по каким-то причинам вы хотите заставить Vite пересобрать зависимости, можно либо запустить dev-сервер с опцией командной строки --force
, либо вручную удалить каталог кэша node_modules/.vite
.
Кэш браузера
Решённые запросы на зависимость сильно кэшируются с HTTP-заголовками max-age=31536000,immutable
для повышения производительности перезагрузки страниц во время разработки. После кэширования эти запросы больше никогда не попадут на dev-сервер. Они автоматически аннулируются добавляемым запросом версии, если установлена другая версия (как отражено в файле блокировки менеджера пакетов). Если вы хотите отладить свои зависимости, внося локальные правки, вы можете это сделать:
- Временно отключите кэш на вкладке «Сеть» инструментов разработчика браузера;
- Перезапустите dev-сервер Vite с флагом
--force
, чтобы пересобрать пакет; - Перезагрузите страницу.