Vue Front-end Инженер

Vue Front-end Инженер

Роадмап навыков для прокачки

Основы Vite

VueJSBuild ToolsVite

Основная идея

Vite — современный сборщик для веб-приложений, созданный автором Vue.js. Он использует нативные ES-модули браузера в режиме разработки, что обеспечивает мгновенный запуск сервера и быструю перезагрузку при изменениях кода (HMR). Для продакшена Vite использует Rollup для оптимизированной сборки.

Ключевые аспекты

  • Мгновенный старт — сервер запускается за миллисекунды
  • HMR (Hot Module Replacement) — мгновенное обновление без потери состояния
  • ES-модули — нативная поддержка import/export в браузере
  • Оптимизированная сборка — Rollup для production
  • Поддержка фреймворков — Vue, React, Svelte из коробки

Базовые команды

bash
# Создание проекта
npm create vite@latest my-app -- --template vue
 
# Установка зависимостей
cd my-app && npm install
 
# Запуск dev-сервера
npm run dev
 
# Сборка для production
npm run build
 
# Просмотр production сборки
npm run preview

Частые ошибки

  • Путают режим разработки и production — разное поведение сборки
  • Забывают про .env файлы — переменные должны начинаться с VITE_
  • Неправильные пути к ассетам — используйте import или public папку
  • Игнорируют vite.config.js — важен для настройки алиасов и плагинов

Рекомендации

  • Используйте официальный шаблон npm create vite@latest
  • Настройте алиас @ для удобных импортов
  • Храните статические файлы в папке public
  • Проверяйте production сборку командой npm run preview

Введение и проблематика

Традиционные сборщики вроде Webpack при запуске анализируют весь проект и создают bundle. С ростом проекта время запуска увеличивается до минут. Vite решает эту проблему, используя нативные ES-модули браузера — сервер стартует мгновенно, а модули загружаются по требованию.

Vite (произносится «вит», французское слово «быстрый») — сборщик нового поколения от создателя Vue.js. Он стал стандартом для Vue-проектов и поддерживает React, Svelte и другие фреймворки.


Почему Vite быстрый

Режим разработки

В режиме разработки Vite не собирает bundle. Вместо этого:

  1. Сервер стартует мгновенно
  2. Браузер запрашивает модули через ES imports
  3. Vite трансформирует только запрошенные файлы
  4. При изменении файла обновляется только он (HMR)
text
Традиционный bundler:
[Весь проект] → [Сборка всего] → [Bundle] → Браузер

Vite:
Браузер запрашивает → Vite трансформирует по требованию

Режим production

Для production Vite использует Rollup — проверенный bundler с отличной оптимизацией:

  • Tree-shaking (удаление неиспользуемого кода)
  • Code splitting (разделение на чанки)
  • Минификация
  • Оптимизация ассетов

Создание проекта

Быстрый старт

bash
# Создание Vue-проекта
npm create vite@latest my-vue-app -- --template vue
 
# Или с TypeScript
npm create vite@latest my-vue-app -- --template vue-ts
 
# Переход в папку и установка зависимостей
cd my-vue-app
npm install
 
# Запуск dev-сервера
npm run dev

Доступные шаблоны

bash
# Vanilla JavaScript
npm create vite@latest app -- --template vanilla
 
# Vue
npm create vite@latest app -- --template vue
 
# React
npm create vite@latest app -- --template react
 
# Svelte
npm create vite@latest app -- --template svelte

Структура проекта

text
my-vue-app/
├── public/           # Статические файлы (копируются как есть)
│   └── favicon.ico
├── src/
│   ├── assets/       # Ассеты (обрабатываются сборщиком)
│   │   └── logo.svg
│   ├── components/
│   │   └── HelloWorld.vue
│   ├── App.vue
│   └── main.js       # Точка входа
├── index.html        # HTML-шаблон (в корне!)
├── vite.config.js    # Конфигурация Vite
└── package.json
⚠️

В Vite файл index.html находится в корне проекта, а не в папке public. Это точка входа для dev-сервера.


Основные команды

package.json scripts

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

Описание команд

КомандаОписание
npm run devЗапуск dev-сервера с HMR
npm run buildСборка для production в папку dist
npm run previewЛокальный просмотр production сборки
bash
# Dev-сервер (по умолчанию http://localhost:5173)
npm run dev
 
# Сборка
npm run build
 
# Просмотр сборки (http://localhost:4173)
npm run preview

Конфигурация Vite

Базовый vite.config.js

Code Example 1: Что делает функция defineConfig и зачем подключается плагин vue()?

js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
 
export default defineConfig({
  plugins: [vue()],
})

Расширенная конфигурация

Code Example 2: Что настраивают секции resolve.alias, server и build в данной конфигурации? Для чего нужен алиас @?

js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
 
export default defineConfig({
  plugins: [vue()],
 
  // Алиасы путей
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src'),
      '@components': resolve(__dirname, 'src/components'),
    },
  },
 
  // Настройки сервера
  server: {
    port: 3000,
    open: true, // Открыть браузер автоматически
  },
 
  // Настройки сборки
  build: {
    outDir: 'dist',
    sourcemap: true,
  },
})

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

Code Example 3: Какой алиас используется в этом импорте и какой реальный путь он заменяет?

vue
<script setup>
// Вместо относительных путей
// import MyComponent from '../../components/MyComponent.vue'
 
// Используем алиас
import MyComponent from '@/components/MyComponent.vue'
</script>

Работа с ассетами

Импорт изображений

Code Example 4: Чем отличается обычный импорт изображения от импорта с суффиксом ?raw? Как используется импортированный URL в шаблоне?

vue
<script setup>
// Импорт как URL
import logoUrl from '@/assets/logo.svg'
 
// Импорт как строка (для маленьких файлов)
import iconRaw from '@/assets/icon.svg?raw'
</script>
 
<template>
  <img :src="logoUrl" alt="Logo" />
</template>

Папка public

Файлы в public/ копируются в корень сборки без обработки:

vue
<template>
  <!-- Файл public/images/photo.jpg -->
  <img src="/images/photo.jpg" alt="Photo" />
</template>

Различия public и assets

Аспектpublic/src/assets/
ОбработкаКопируются как естьОптимизируются
ХэшированиеНетДа (для кэширования)
ИмпортПо абсолютному путиЧерез import
Использованиеfavicon, robots.txtИзображения в компонентах

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

Создание .env файлов

bash
# .env — для всех режимов
VITE_API_URL=https://api.example.com
 
# .env.development — только для разработки
VITE_API_URL=http://localhost:3000/api
 
# .env.production — только для production
VITE_API_URL=https://api.production.com
⚠️

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

Использование переменных

Code Example 5: Как в Vite получить доступ к переменным окружения? Какие встроенные переменные доступны через import.meta.env?

js
// В JavaScript/Vue
const apiUrl = import.meta.env.VITE_API_URL
 
// Встроенные переменные
console.log(import.meta.env.MODE)      // 'development' или 'production'
console.log(import.meta.env.DEV)       // true в dev режиме
console.log(import.meta.env.PROD)      // true в production
console.log(import.meta.env.BASE_URL)  // базовый URL

Hot Module Replacement (HMR)

HMR обновляет код в браузере без полной перезагрузки страницы:

Code Example 6: Что произойдёт при изменении шаблона или стилей этого компонента в режиме разработки Vite? Сохранится ли значение count?

vue
<script setup>
import { ref } from 'vue'
 
const count = ref(0)
</script>
 
<template>
  <button @click="count++">
    Count: {{ count }}
  </button>
</template>

При изменении шаблона или стилей:

  • Страница не перезагружается
  • Состояние count сохраняется
  • Обновляется только изменённая часть

Практический пример

Полная настройка Vue-проекта

Code Example 7: Что делают секции server.proxy, css.preprocessorOptions и build.rollupOptions.output.manualChunks в этой конфигурации?

js
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
 
export default defineConfig({
  plugins: [vue()],
 
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src'),
    },
  },
 
  server: {
    port: 3000,
    proxy: {
      // Проксирование API запросов
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
      },
    },
  },
 
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@import "@/styles/variables.scss";`,
      },
    },
  },
 
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['vue', 'vue-router', 'pinia'],
        },
      },
    },
  },
})

Сравнение с Webpack

АспектViteWebpack
Время стартаМгновенноМедленно (секунды-минуты)
HMRОчень быстрыйМедленнее
КонфигурацияМинимальнаяСложная
Production bundlerRollupWebpack
Экосистема плагиновРастущаяОгромная
Поддержка legacyЧерез плагинИз коробки

Вопросы интервьюера

Q: Почему Vite быстрее Webpack в режиме разработки?

Vite использует нативные ES-модули браузера и не собирает bundle. Модули загружаются по требованию, а при изменении обновляется только изменённый файл.

Q: Что использует Vite для production сборки?

Rollup — проверенный bundler с отличной оптимизацией, tree-shaking и code splitting.

Q: Как работает HMR в Vite?

При изменении файла Vite отправляет обновление через WebSocket. Браузер заменяет только изменённый модуль без полной перезагрузки страницы.

Q: Почему переменные окружения должны начинаться с VITE_?

Для безопасности. Только переменные с префиксом VITE_ попадают в клиентский код. Остальные остаются только на сервере сборки.


Источники

Code Example 1: Базовая конфигурация Vite

❓ Что делает функция defineConfig и зачем подключается плагин vue()?

js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
 
export default defineConfig({
  plugins: [vue()],
})

Code Example 2: Расширенная конфигурация Vite

❓ Что настраивают секции resolve.alias, server и build в данной конфигурации? Для чего нужен алиас @?

js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
 
export default defineConfig({
  plugins: [vue()],
 
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src'),
      '@components': resolve(__dirname, 'src/components'),
    },
  },
 
  server: {
    port: 3000,
    open: true,
  },
 
  build: {
    outDir: 'dist',
    sourcemap: true,
  },
})

Code Example 3: Использование алиасов в Vue-компоненте

❓ Какой алиас используется в этом импорте и какой реальный путь он заменяет?

vue
<script setup>
import MyComponent from '@/components/MyComponent.vue'
</script>

Code Example 4: Импорт ассетов в Vue-компоненте

❓ Чем отличается обычный импорт изображения от импорта с суффиксом ?raw? Как используется импортированный URL в шаблоне?

vue
<script setup>
import logoUrl from '@/assets/logo.svg'
import iconRaw from '@/assets/icon.svg?raw'
</script>
 
<template>
  <img :src="logoUrl" alt="Logo" />
</template>

Code Example 5: Переменные окружения в Vite

❓ Как в Vite получить доступ к переменным окружения? Какие встроенные переменные доступны через import.meta.env?

js
const apiUrl = import.meta.env.VITE_API_URL
 
console.log(import.meta.env.MODE)
console.log(import.meta.env.DEV)
console.log(import.meta.env.PROD)
console.log(import.meta.env.BASE_URL)

Code Example 6: Компонент с HMR

❓ Что произойдёт при изменении шаблона или стилей этого компонента в режиме разработки Vite? Сохранится ли значение count?

vue
<script setup>
import { ref } from 'vue'
 
const count = ref(0)
</script>
 
<template>
  <button @click="count++">
    Count: {{ count }}
  </button>
</template>

Code Example 7: Полная настройка Vue-проекта

❓ Что делают секции server.proxy, css.preprocessorOptions и build.rollupOptions.output.manualChunks в этой конфигурации?

js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
 
export default defineConfig({
  plugins: [vue()],
 
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src'),
    },
  },
 
  server: {
    port: 3000,
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
      },
    },
  },
 
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@import "@/styles/variables.scss";`,
      },
    },
  },
 
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['vue', 'vue-router', 'pinia'],
        },
      },
    },
  },
})