Интеграция Rolldown
Vite планирует интегрировать Rolldown — JavaScript-бандлер на Rust, чтобы улучшить производительность сборки и расширить возможности.
Что такое Rolldown?
Rolldown — это современный высокопроизводительный JavaScript-бандлер, написанный на Rust. Он разработан как замена Rollup с сохранением совместимости, но с существенным приростом производительности.
Ключевые принципы Rolldown:
- Скорость: Реализация на Rust для максимальной производительности
- Совместимость: Работает с существующими плагинами Rollup
- Оптимизация: включает функции, выходящие за рамки возможностей esbuild и Rollup
Почему Vite переходит на Rolldown
Унификация: Сейчас Vite использует esbuild для предварительной сборки зависимостей и Rollup для продакшн-сборки. Rolldown объединит эти процессы в один высокопроизводительный инструмент, упрощая архитектуру.
Производительность: Реализация на Rust дает значительный прирост скорости по сравнению с JavaScript-решениями. Хотя конкретные показатели зависят от проекта, первые тесты показывают впечатляющие результаты.
Дополнительные возможности: Rolldown предоставляет функции, недоступные в Rollup или esbuild, такие как расширенный контроль разделения чанков, встроенный HMR (горячая замена модулей) и плагин Module Federation.
Подробнее о причинах создания Rolldown можно узнать в официальной документации.
Преимущества тестирования rolldown-vite
- Более быстрая сборка, особенно для крупных проектов
- Улучшение будущей интеграции Rolldown в Vite, благодаря обратной связи
- Подготовка своих проектов к официальному переходу на Rolldown
Как попробовать Rolldown
Версия Vite на базе Rolldown доступна в виде отдельного пакета rolldown-vite
. Если у вас есть vite
в качестве прямой зависимости, вы можете создать псевдоним для пакета vite
, указывающий на rolldown-vite
в package.json
вашего проекта — это должно сработать как полная замена без дополнительной настройки:
{
"dependencies": {
"vite": "^7.0.0"
"vite": "npm:rolldown-vite@latest"
}
}
Если вы используете Vitepress или мета-фреймворк, в котором vite
указан как peer-зависимость, вам нужно переопределить зависимость vite
в вашем package.json
. Это работает немного по-разному в зависимости от используемого менеджера пакетов:
{
"overrides": {
"vite": "npm:rolldown-vite@latest"
}
}
{
"resolutions": {
"vite": "npm:rolldown-vite@latest"
}
}
{
"pnpm": {
"overrides": {
"vite": "npm:rolldown-vite@latest"
}
}
}
{
"overrides": {
"vite": "npm:rolldown-vite@latest"
}
}
После добавления переопределений переустановите зависимости и запускайте сервер разработки или сборку проекта как обычно. Дополнительные изменения конфигурации не требуются.
Известные ограничения
Хотя Rolldown стремится быть полной заменой Rollup, некоторые функции всё ещё находятся в разработке, а также есть небольшие преднамеренные различия в поведении. Полный список можно найти в этом PR на GitHub, который регулярно обновляется.
Предупреждения валидации опций
Rolldown выводит предупреждение при передаче неизвестных или некорректных опций. Поскольку некоторые опции, доступные в Rollup, не поддерживаются Rolldown, вы можете столкнуться с предупреждениями в зависимости от опций, которые вы или используемый мета-фреймворк задали. Ниже приведён пример такого предупреждения:
Warning validate output options.
- For the "generatedCode". Invalid key: Expected never but received "generatedCode".
Если вы не передаёте эту опцию самостоятельно, проблема должна быть исправлена в используемом фреймворке.
Различия в API
От manualChunks
к advancedChunks
Хотя Rolldown поддерживает опцию manualChunks
, также доступную в Rollup, она помечена как устаревшая. Вместо неё предлагается использовать более детализированную настройку через опцию advancedChunks
, которая больше похожа на splitChunk
в webpack:
// Устаревшая конфигурация (Rollup)
export default {
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (/\/react(?:-dom)?/.test(id)) {
return 'vendor'
}
}
}
}
}
}
// Обновлённая конфигурация (Rolldown)
export default {
build: {
rollupOptions: {
output: {
advancedChunks: {
groups: [{ name: 'vendor', test: /\/react(?:-dom)?/ }]
}
}
}
}
}
Производительность
rolldown-vite
ориентирован на обеспечение совместимости с существующей экосистемой, поэтому настройки по умолчанию направлены на максимально плавный переход. Дополнительный прирост производительности можно получить, перейдя на более быстрые внутренние плагины на базе Rust и применив другие кастомизации.
Подключение нативных плагинов
Благодаря Rolldown и Oxc, различные внутренние плагины Vite, такие как плагин alias или resolve, были переведены на Rust. Нативные плагины теперь включены по умолчанию, с установленным значением по умолчанию 'v1'
.
Если вы столкнулись с какими-либо проблемами, попробуйте изменить опцию experimental.enableNativePlugin
в конфигурации Vite на 'resolver'
или false
в качестве временного решения. Обратите внимание, что эта опция будет удалена в будущем.
Использование React refresh transform от Oxc
@vitejs/plugin-react
v5.0.0+ использует React refresh transform от Oxc. Если вы не используете плагины Babel (включая React compiler), теперь вся трансформация будет выполняться Oxc, что улучшит производительность сборки без каких-либо изменений, кроме обновления @vitejs/plugin-react
.
Если вы используете @vitejs/plugin-react-swc
без плагинов SWC и пользовательских настроек SWC, вы можете перейти на плагин @vitejs/plugin-react
, чтобы задействовать Oxc.
Плагин @vitejs/plugin-react-oxc
устарел
Ранее мы рекомендовали использовать @vitejs/plugin-react-oxc
для задействования React refresh transform от Oxc. Однако мы объединили реализацию в @vitejs/plugin-react
, чтобы упростить переход на rolldown-vite
. @vitejs/plugin-react-oxc
теперь устарел и больше не будет обновляться.
Обёртка withFilter
Авторы плагинов могут использовать возможность фильтрации хуков, чтобы снизить издержки на взаимодействие между средами выполнения Rust и JavaScript. Однако, если какие-то используемые вами плагины пока ещё не применяют эту функцию, но вы всё равно хотите получить от неё выгоду, вы можете обернуть плагин вручную, используя обёртку withFilter
:
// В вашем vite.config.ts
import { withFilter, defineConfig } from 'vite'
import svgr from 'vite-plugin-svgr'
export default defineConfig({
plugins: [
// Загружаем плагин `svgr` только для файлов, которые заканчиваются на `.svg?react`
withFilter(
svgr({
/*...*/
}),
{ load: { id: /\.svg\?react$/ } },
),
],
})
Сообщение о проблемах
Поскольку это экспериментальная интеграция, вы можете столкнуться с проблемами. Если это произошло, пожалуйста, сообщайте о них в репозитории vitejs/rolldown-vite
, а не в основном репозитории Vite.
При сообщении о проблемах пожалуйста, следуйте соответствующему шаблону issue и укажите запрашиваемую информацию, которая обычно включает:
- Минимальный пример для воспроизведения проблемы
- Данные о вашем окружении (ОС, версия Node, пакетный менеджер)
- Соответствующие сообщения об ошибках или логи
Для оперативного обсуждения и решения проблем присоединяйтесь к Discord Rolldown.
Политика версионирования
Политика версионирования rolldown-vite
согласована с основным пакетом Vite: его мажорные и минорные версии синхронизированы с обычным Vite. Это гарантирует, что все фичи, появившиеся в конкретной минорной версии Vite, также будут присутствовать в соответствующей минорной версии rolldown-vite
. Однако важно отметить, что патч-версии не синхронизированы между этими двумя проектами. Если вы хотите узнать, была ли конкретная правка из обычного Vite включена в rolldown-vite
, вы всегда можете проверить отдельный changelog rolldown-vite
.
Также обратите внимание, что rolldown-vite
считается экспериментальным проектом. В связи с этим возможны обратимо несовместимые изменения даже в патч-версиях. Кроме того, rolldown-vite
получает обновления только для самой последней минорной версии — даже важные багфиксы и обновления безопасности не выпускаются для более старых мажорных или минорных версий.
Планы на будущее
Пакет rolldown-vite
— это временное решение для сбора отзывов и стабилизации интеграции Rolldown. В будущем эта функциональность будет перенесена в основной репозиторий Vite.
Мы призываем вас опробовать rolldown-vite
и внести вклад в его развитие через отзывы и сообщения о проблемах.
В будущем мы также представим «режим полной сборки» (Full Bundle Mode) для Vite, который будет обслуживать собранные файлы как в продакшене, так и в режиме разработки.
Зачем нужен режим полной сборки?
Vite известен своим подходом к серверу разработки без сборки (unbundled), что стало одной из основных причин его скорости и популярности при первом выпуске. Изначально этот подход был экспериментом, чтобы проверить, насколько можно повысить производительность сервера разработки без традиционной сборки.
Однако по мере роста масштабов и сложности проектов возникли две основные проблемы:
Несоответствие между разработкой и продакшеном: JavaScript без сборки в разработке и собранный пакет в продакшене ведут себя по-разному. Это может приводить к ошибкам, которые проявляются только в продакшене, усложняя отладку.
Снижение производительности в режиме разработки: Подход без сборки приводит к раздельной загрузке каждого модуля, что создаёт большое количество сетевых запросов. Хотя это не влияет на продакшен, это вызывает значительные накладные расходы при запуске сервера разработки и обновлении страницы в процессе разработки. Особенно заметно это проявляется в крупных приложениях, где необходимо обрабатывать сотни или даже тысячи отдельных запросов. Эти узкие места становятся ещё более серьёзными при использовании сетевых прокси, что приводит к увеличению времени перезагрузки и ухудшению опыта разработчиков.
Благодаря интеграции с Rolldown у нас появилась возможность унифицировать процесс разработки и продакшена, сохраняя при этом фирменную производительность Vite. Режим полной сборки позволит использовать собранные файлы не только в продакшене, но и во время разработки, сочетая преимущества обоих подходов:
- Быстрый запуск даже для крупных приложений
- Единообразное поведение в разработке и продакшене
- Снижение сетевой нагрузки при обновлении страниц
- Сохранение эффективного HMR поверх ESM-вывода
Изначально режим полной сборки будет доступен как опциональная функция. Как и в случае с интеграцией Rolldown, мы планируем сделать его режимом по умолчанию после сбора отзывов и достижения необходимой стабильности работы.
Руководство для авторов плагинов и фреймворков
СОВЕТ
Данный раздел в первую очередь будет полезен разработчикам плагинов и создателям фреймворков. Обычным пользователям можно смело пропустить эту часть.
Обзор ключевых изменений
- Для сборки теперь используется Rolldown (ранее использовался Rollup)
- Для оптимизации теперь используется Rolldown (ранее использовался esbuild)
- Поддержка CommonJS теперь обрабатывается Rolldown (ранее использовался @rollup/plugin-commonjs)
- Для понижения синтаксиса теперь используется Oxc (ранее использовался esbuild)
- Для минификации CSS по умолчанию используется Lightning CSS (ранее использовался esbuild)
- Для минификации JS по умолчанию теперь используется Oxc minifier (ранее использовался esbuild)
- Для сборки конфигурации теперь используется Rolldown (ранее использовался esbuild)
Определение rolldown-vite
ПРЕДУПРЕЖДЕНИЕ
В большинстве случаев вам не нужно определять, работает ли ваш плагин с rolldown-vite
или обычным vite
. Следует стремиться к одинаковому поведению в обеих средах без условных ветвлений.
Если вам всё же требуется разное поведение для rolldown-vite
, есть два способа его определить:
Проверка существования this.meta.rolldownVersion
:
const plugin = {
resolveId() {
if (this.meta.rolldownVersion) {
// логика для rolldown-vite
} else {
// логика для rollup-vite
}
},
}
СОВЕТ
Начиная с Vite 7.0.0, this.meta
доступен во всех хуках. В предыдущих версиях this.meta
не был доступен в специфичных для Vite хуках, таких как хук config
.
Проверка существования экспорта rolldownVersion
:
import * as vite from 'vite'
if (vite.rolldownVersion) {
// логика для rolldown-vite
} else {
// логика для rollup-vite
}
Если у вас есть vite
в зависимостях (не peer dependency), экспорт rolldownVersion
полезен, так как его можно использовать из любого места вашего кода.
Игнорирование проверки опций в Rolldown
Как уже упоминалось выше, Rolldown выводит предупреждение при передаче неизвестных или некорректных опций.
Эту проблему можно решить, условно передавая опцию после проверки, что код выполняется с rolldown-vite
, как показано выше.
transformWithEsbuild
требует отдельной установки esbuild
Поскольку Vite больше не использует esbuild
, теперь esbuild
является необязательной одноранговой зависимостью. Если ваш плагин использует transformWithEsbuild
, необходимо добавить esbuild
в зависимости плагина или пользователю придется установить его вручную.
Рекомендуемый путь миграции — использовать новую экспортируемую функцию transformWithOxc
, которая работает с Oxc вместо esbuild
.
Слой совместимости для опций esbuild
Rolldown-Vite включает слой совместимости, преобразующий опции esbuild
в соответствующие опции Oxc или rolldown
. Как протестировано в ecosystem-ci, это работает во многих случаях, включая простые плагины esbuild
. Однако важно отметить, что поддержка опций esbuild
будет удалена в будущем. Мы рекомендуем использовать соответствующие опции Oxc или rolldown
. Вы можете получить опции, установленные слоем совместимости, через хук configResolved
.
const plugin = {
name: 'log-config',
configResolved(config) {
console.log('options', config.optimizeDeps, config.oxc)
},
},
Фильтрация хуков
Rolldown представил функцию фильтрации хуков для уменьшения накладных расходов на взаимодействие между средами выполнения Rust и JavaScript. Использование этой функции позволяет повысить производительность вашего плагина. Эта возможность также поддерживается в Rollup 4.38.0+ и Vite 6.3.0+. Для обеспечения обратной совместимости вашего плагина со старыми версиями убедитесь, что фильтрация также выполняется внутри обработчиков хуков.
СОВЕТ
Пакет @rolldown/pluginutils
экспортирует несколько утилит для фильтрации хуков, таких как exactRegex
и prefixRegex
.
Преобразование контента в JavaScript в хуках load
или transform
Если вы преобразуете контент других типов в JavaScript в хуках load
или transform
, возможно, потребуется добавить moduleType: 'js'
к возвращаемому значению.
const plugin = {
name: 'txt-loader',
load(id) {
if (id.endsWith('.txt')) {
const content = fs.readFile(id, 'utf-8')
return {
code: `export default ${JSON.stringify(content)}`,
moduleType: 'js',
}
}
},
}
Это связано с тем, что Rolldown поддерживает модули, отличные от JavaScript, и определяет тип модуля по расширению файла, если он не указан явно.