Запуск dev-сервера и первая сборка

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

При запуске dev-сервера создаётся локальное окружение разработки со следующими возможностями:

  • мгновенный старт проекта;
  • автоматическая обработка модулей;
  • горячая замена модулей (HMR);
  • поддержка TypeScript без отдельной настройки;
  • автоматическая обработка CSS;
  • работа с импортами изображений, шрифтов и других ресурсов;
  • поддержка .env-переменных;
  • интеграция с плагинами.

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


Подготовка проекта к запуску

После создания проекта структура обычно содержит следующие основные файлы:

project/
├── index.html
├── package.json
├── vite.config.js
├── src/
│   ├── main.js
│   └── style.css
└── node_modules/

Перед запуском dev-сервера устанавливаются зависимости:

npm install

После установки появляется каталог node_modules, содержащий локальные пакеты проекта.


Скрипты в package.json

Основные команды Vite обычно находятся в разделе scripts.

Пример:

{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  }
}

Каждый скрипт отвечает за отдельный режим работы:

Скрипт Назначение
npm run dev запуск dev-сервера
npm run build production-сборка
npm run preview локальный просмотр production-сборки

Запуск dev-сервера

Стандартный запуск выполняется командой:

npm run dev

После запуска Vite выводит информацию в терминал:

VITE v5.0.0 ready in 320 ms

➜  Local:   http://localhost:5173/
➜  Network: use --host to expose

Основные элементы вывода:

Элемент Описание
Local локальный адрес проекта
Network доступ из локальной сети
ready in время старта сервера

По умолчанию Vite использует порт 5173.


Как работает dev-сервер

При открытии страницы браузер сначала получает index.html.

Внутри HTML подключается главный модуль:

<script type="module" src="/src/main.js"></script>

Браузер самостоятельно загружает ES-модули:

import './style.css'
import { createApp } from './app.js'

Vite перехватывает запросы браузера и при необходимости:

  • преобразует TypeScript в JavaScript;
  • обрабатывает JSX;
  • компилирует SCSS;
  • добавляет HMR-код;
  • преобразует импорты npm-пакетов.

Горячая замена модулей (HMR)

Hot Module Replacement — одна из ключевых возможностей Vite.

При изменении файла:

  1. Vite отслеживает изменение;
  2. перестраивает только изменённый модуль;
  3. отправляет обновление браузеру через WebSocket;
  4. браузер заменяет модуль без полной перезагрузки страницы.

Пример:

if (import.meta.hot) {
  import.meta.hot.accept(() => {
    console.log('Модуль обновлён')
  })
}

HMR особенно полезен при работе:

  • с компонентами интерфейса;
  • стилями;
  • крупными приложениями;
  • интерактивными формами;
  • состоянием приложения.

Обновление CSS без перезагрузки

Vite умеет обновлять стили мгновенно.

Изменение файла:

body {
  background: black;
}

применяется в браузере практически моментально без обновления страницы.

Это достигается за счёт динамической замены <style>-блоков внутри документа.


Предварительная оптимизация зависимостей

Во время первого запуска Vite выполняет pre-bundling зависимостей.

Для этого используется:

  • esbuild;
  • кеширование;
  • предварительная обработка CommonJS-модулей.

Например:

import lodash from 'lodash'

Пакет будет заранее оптимизирован и помещён в кеш:

node_modules/.vite

Это значительно ускоряет повторные запуски проекта.


Использование другого порта

Порт можно изменить несколькими способами.

Через CLI

npm run dev -- --port 3000

Через vite.config.js

import { defineConfig } from 'vite'

export default defineConfig({
  server: {
    port: 3000
  }
})

Открытие браузера автоматически

Vite поддерживает автоматическое открытие страницы после запуска сервера.

export default defineConfig({
  server: {
    open: true
  }
})

После запуска браузер автоматически откроет адрес проекта.


Доступ из локальной сети

По умолчанию сервер доступен только локально.

Для доступа с других устройств используется:

npm run dev -- --host

или:

export default defineConfig({
  server: {
    host: true
  }
})

После этого приложение можно открыть с телефона, планшета или другого компьютера внутри сети.


Использование HTTPS

Vite поддерживает локальный HTTPS.

Пример:

export default defineConfig({
  server: {
    https: true
  }
})

В этом режиме браузер может показывать предупреждение о сертификате, поскольку используется локальный self-signed certificate.


Работа proxy в dev-сервере

Proxy используется для обхода CORS-проблем при обращении к backend API.

Пример:

export default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:8000',
        changeOrigin: true
      }
    }
  }
})

Запрос:

fetch('/api/users')

будет автоматически перенаправлен на:

http://localhost:8000/api/users

Переменные окружения

Vite использует .env-файлы.

Пример:

VITE_API_URL=https://example.com

Доступ внутри приложения:

console.log(import.meta.env.VITE_API_URL)

Особенности:

  • доступны только переменные с префиксом VITE_;
  • значения внедряются на этапе сборки;
  • поддерживаются режимы окружения.

Режимы работы (modes)

Vite поддерживает разные конфигурации окружения:

Mode Назначение
development разработка
production production-сборка
staging промежуточное окружение

Пример запуска:

vite --mode staging

Файлы окружения:

.env
.env.development
.env.production
.env.staging

Первая production-сборка

Production-сборка создаётся командой:

npm run build

Во время сборки Vite:

  • анализирует граф модулей;
  • объединяет зависимости;
  • минимизирует код;
  • удаляет dev-инструменты;
  • оптимизирует CSS;
  • генерирует ассеты;
  • создаёт итоговый bundle.

Пример вывода:

dist/index.html
dist/assets/index-3f2d1a.js
dist/assets/index-8c4a12.css

Каталог dist

Результат сборки помещается в папку:

dist/

Типичная структура:

dist/
├── index.html
├── assets/
│   ├── index-82a1d.js
│   ├── vendor-a21fd.js
│   └── style-12bcf.css

Содержимое dist готово к публикации на сервере.


Rollup внутри production-сборки

Хотя dev-сервер Vite работает без традиционного bundling, production-режим использует Rollup.

Rollup отвечает за:

  • tree shaking;
  • code splitting;
  • генерацию чанков;
  • оптимизацию импортов;
  • минимизацию финального размера сборки.

Tree Shaking

Tree shaking удаляет неиспользуемый код.

Пример:

export function used() {}
export function unused() {}

Если импортируется только:

import { used } from './utils.js'

то unused() не попадёт в production bundle.


Code Splitting

Vite автоматически разбивает приложение на чанки.

Пример динамического импорта:

const module = await import('./admin.js')

В результате создаётся отдельный JS-файл, который загружается только при необходимости.

Это уменьшает размер первоначальной загрузки приложения.


Минификация кода

Во время production-сборки выполняется:

  • удаление комментариев;
  • сокращение имён;
  • удаление лишних пробелов;
  • упрощение выражений.

Пример:

function sum(a, b) {
  return a + b
}

после минимизации:

function n(n,r){return n+r}

Хеширование файлов

Vite добавляет хеши к именам файлов:

index-a8f31c.js

Это необходимо для:

  • эффективного кеширования;
  • автоматического обновления файлов;
  • предотвращения конфликтов версий.

Просмотр production-сборки

После сборки используется команда:

npm run preview

Vite запускает локальный сервер, обслуживающий содержимое dist.

Это позволяет проверить production-версию приложения перед публикацией.


Отличие dev-режима от production

Характеристика Dev Production
Скорость запуска очень высокая не важна
Bundling отсутствует полный
Минификация нет есть
HMR есть нет
Оптимизация минимальная максимальная
Source maps подробные сокращённые

Source Maps

Во время разработки source maps помогают сопоставлять итоговый код с исходными файлами.

В production source maps могут отключаться:

export default defineConfig({
  build: {
    sourcemap: false
  }
})

или включаться:

export default defineConfig({
  build: {
    sourcemap: true
  }
})

Настройка выходной директории

Каталог сборки можно изменить:

export default defineConfig({
  build: {
    outDir: 'build'
  }
})

После этого сборка будет создаваться в папке:

build/

Очистка директории сборки

Перед новой сборкой Vite автоматически очищает каталог dist.

Поведение можно изменить:

export default defineConfig({
  build: {
    emptyOutDir: false
  }
})

Генерация manifest-файла

Manifest используется backend-приложениями для поиска итоговых ассетов.

export default defineConfig({
  build: {
    manifest: true
  }
})

После сборки создаётся:

dist/.vite/manifest.json

Этот механизм особенно важен при интеграции Vite:

  • с серверным рендерингом;
  • с backend-фреймворками;
  • с CMS;
  • с PHP-приложениями;
  • с шаблонизаторами.

Анализ размера сборки

Для анализа bundle часто подключаются плагины:

  • visualizer;
  • inspect;
  • analyzer.

Пример установки:

npm install --save-dev rollup-plugin-visualizer

Подключение:

import { visualizer } from 'rollup-plugin-visualizer'

export default defineConfig({
  plugins: [
    visualizer()
  ]
})

После сборки формируется HTML-отчёт со структурой bundle.


Типичный цикл разработки

Полный цикл работы с Vite обычно выглядит следующим образом:

  1. запуск dev-сервера;
  2. изменение файлов;
  3. мгновенное обновление браузера;
  4. тестирование функциональности;
  5. production-сборка;
  6. проверка через preview;
  7. публикация dist на сервере.

Наиболее распространённые проблемы

Порт уже занят

Ошибка:

Port 5173 is already in use

Решение:

npm run dev -- --port 3001

Модули не обновляются

Причины:

  • сломанный HMR;
  • ошибки импорта;
  • циклические зависимости;
  • кеш браузера.

Иногда помогает удаление кеша:

node_modules/.vite

Ошибки CommonJS-пакетов

Некоторые старые библиотеки плохо работают с ESM.

Решение:

export default defineConfig({
  optimizeDeps: {
    include: ['legacy-library']
  }
})

Ошибки путей в production

Неправильная настройка base приводит к ошибкам загрузки ассетов.

Пример:

export default defineConfig({
  base: '/app/'
})

Настройка особенно важна при размещении проекта не в корне домена.