Skip to content

Beyond Fast

ViteConf 2023

Watch the replay!

Почему Vite

Проблемы

До того, как модули ES стали доступны в браузерах, у разработчиков не было встроенного механизма для модульного написания JavaScript. Вот почему мы все знакомы с концепцией "bundling": с использованием инструментов, которые сканируют, обрабатывают и объединяют наши исходные модули в файлы, которые можно запускать в браузере.

Со временем мы увидели такие инструменты, как webpack, Rollup и Parcel, что значительно улучшило опыт разработки для разработчиков интерфейса.

При холодном запуске сервера разработки установка сборки на основе сборщика должна жадно просканировать и собрать все ваше приложение, прежде чем оно сможет быть обслужено.

Vite улучшает время запуска сервера разработки, сначала разделяя модули в приложении на две категории: dependencies и source code.

  • Dependencies(зависимости) в основном представляют собой простой JavaScript, который не часто меняется во время разработки. Некоторые большие зависимости (например, библиотеки компонентов с сотнями модулей) также довольно дороги в обработке. Зависимости также могут поставляться в различных форматах модулей (например, ESM или CommonJS).

    Vite pre-bundles dependencies с помощью esbuild. esbuild написан на Go и предварительно связывает зависимости в 10-100 раз быстрее, чем сборщики на основе JavaScript.

  • Source code(исходный код) часто содержит нестандартный JavaScript, который необходимо преобразовать (например, компоненты JSX, CSS или Vue/Svelte), и будет очень часто редактироваться. Кроме того, не весь исходный код нужно загружать одновременно (например, при разделении кода на основе маршрута).

    Vite предоставляет исходный код через нативный ESM. По сути, это позволяет браузеру взять на себя часть работы сборщика: Vite нужно только преобразовывать и обслуживать исходный код по запросу, когда браузер его запрашивает. Код условного динамического импорта обрабатывается только в том случае, если он фактически используется на текущем экране.

Bundle based dev server entry ··· route route module module module module ··· Bundle Server ready
Native ESM based dev server entry ··· route route module module module module ··· Server ready Dynamic import (code split point) HTTP request

Медленные обновления

Когда файл редактируется в настройке сборки на основе бандлера, пересобирать весь пакет неэффективно по очевидной причине: скорость обновления будет линейно ухудшаться с размером приложения.

В некоторых упаковщиках сервер разработки запускает сборку в памяти, поэтому ему нужно только аннулировать часть своего графа модуля при изменении файла, но ему все равно нужно заново создать весь пакет и перезагрузить веб-страницу. Реконструкция пакета может быть дорогостоящей, а перезагрузка страницы сбрасывает текущее состояние приложения. Вот почему некоторые сборщики поддерживают горячую замену модуля (HMR): позволяя модулю «горячую замену» себя, не затрагивая остальную часть страницы. Это значительно улучшает DX, однако на практике мы обнаружили, что даже скорость обновления HMR значительно ухудшается по мере роста размера приложения.

В Vite HMR выполняется поверх собственного ESM. Когда файл редактируется, Vite нужно только точно аннулировать цепочку между редактируемым модулем и его ближайшей границей HMR (в большинстве случаев только сам модуль), что делает обновления HMR постоянно быстрыми независимо от размера вашего приложения.

Vite также использует заголовки HTTP для ускорения полной перезагрузки страницы (опять же, пусть браузер сделает за нас больше работы): запросы модулей исходного кода обусловливаются с помощью 304 Not Modified, а запросы модулей зависимостей строго кэшируются с помощью Cache-Control: max-age=31536000,immutable, чтобы они больше не попадали на сервер после кэширования.

Как только вы почувствуете, насколько быстр Vite, мы очень сомневаемся, что вы снова захотите мириться с пакетной разработкой.

Зачем объединять для продакшена

Несмотря на то, что нативный ESM теперь широко поддерживается, поставка разделенного ESM в производственной среде по-прежнему неэффективна (даже с HTTP/2) из-за дополнительных сетевых циклов, вызванных вложенным импортом. Чтобы получить оптимальную производительность загрузки в продакшене, все же лучше связать свой код с встряхиванием дерева, отложенной загрузкой и общим разделением фрагментов (для лучшего кэширования).

Обеспечить оптимальные выходные данные и поведенческую согласованность между сервером разработки и рабочей сборкой непросто. Вот почему Vite поставляется с предварительно настроенной командой сборки, которая включает множество оптимизаций производительности из коробки.

Почему бы не связать с esbuild?

Текущий API плагинов Vite несовместим с использованием esbuild в качестве сборщика. Несмотря на то, что esbuild работает быстрее, внедрение Vite гибкого API-интерфейса и инфраструктуры плагинов Rollup во многом способствовало его успеху в экосистеме. На данный момент мы считаем, что Rollup предлагает лучший компромисс между производительностью и гибкостью.

Rollup также работает над повышением производительности, переключив парсер на SWC в версии 4. И в настоящее время предпринимаются усилия по созданию Rust-порта Rollup под названием Rolldown. Как только Rolldown будет готов, он сможет заменить Rollup и esbuild в Vite, значительно улучшив производительность сборки и устранив несоответствия между разработкой и сборкой. Вы можете посмотреть выступление Эвана Ю на ViteConf 2023 для более подробной информации.

Чем Vite отличается от X?

Вы можете ознакомиться с разделом Сравнений для получения более подробной информации о том, чем Vite отличается от других подобных инструментов.

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