Skip to content

Предварительное объединение зависимостей

Когда вы запускаете vite в первый раз, Vite предварительно собирает зависимости вашего проекта перед локальной загрузкой сайта. По умолчанию это происходит автоматически и прозрачно.

Зачем?

Так Vite выполняет то, что мы называем «предварительным объединением зависимостей». Этот процесс служит двум целям:

  1. Совместимость CommonJS и UMD: во время разработки сборщик Vite использует весь код как собственный ESM. Поэтому Vite должен сначала преобразовать зависимости, поставляемые как CommonJS или UMD, в ESM.

    При преобразовании зависимостей CommonJS Vite выполняет интеллектуальный анализ импорта, чтобы именованный импорт в модули CommonJS работал должным образом, даже если экспорт назначается динамически (например, React):

    js
    // работает как ожидалось
    import React, { useState } from 'react'
  2. Производительность: 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 в вашем конфиге.

js
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-сервер. Они автоматически аннулируются добавляемым запросом версии, если установлена другая версия (как отражено в файле блокировки менеджера пакетов). Если вы хотите отладить свои зависимости, внося локальные правки, вы можете это сделать:

  1. Временно отключите кэш на вкладке «Сеть» инструментов разработчика браузера;
  2. Перезапустите dev-сервер Vite с флагом --force, чтобы пересобрать пакет;
  3. Перезагрузите страницу.

Выпущено под лицензией MIT. (dev)