Конфигурация в Vite строится вокруг файла
vite.config.js, vite.config.ts или их
ESM-вариантов. Главная задача этого файла — экспортировать объект
конфигурации, который Vite использует при запуске dev-сервера, сборке
проекта и preview-режиме.
Базовый вариант конфигурации выглядит так:
export default {
server: {
port: 3000
}
}
После запуска Vite автоматически считывает экспортируемый объект и применяет настройки.
Поддерживаются разные форматы экспорта:
defineConfig;Самый простой вариант — экспортировать объект напрямую.
export default {
base: '/',
server: {
port: 5173
},
build: {
outDir: 'dist'
}
}
Такой подход подходит для:
Vite интерпретирует объект как итоговую конфигурацию.
Несмотря на простоту, прямой экспорт имеет ограничения.
В JavaScript IDE не всегда корректно понимает структуру конфигурации.
Например:
export default {
servre: {
port: 3000
}
}
Опечатка servre не будет обнаружена автоматически.
Без дополнительных подсказок IDE хуже автодополняет:
server;build;resolve;css;plugins;optimizeDeps;define.При росте проекта конфигурация начинает зависеть от:
Обычный объект становится неудобным.
defineConfigVite предоставляет вспомогательную функцию
defineConfig.
import { defineConfig } from 'vite'
export default defineConfig({
server: {
port: 3000
}
})
Технически defineConfig почти ничего не делает во время
выполнения. Основная задача функции — улучшение типизации и DX
(Developer Experience).
defineConfigIDE начинает понимать структуру конфигурации.
Ошибки обнаруживаются сразу:
export default defineConfig({
servre: {
port: 3000
}
})
Редактор покажет, что servre не существует.
При вводе появляются подсказки:
export default defineConfig({
server: {
// подсказки:
// host
// port
// open
// proxy
}
})
Это особенно важно в крупных проектах.
В TypeScript defineConfig раскрывает все типы
конфигурации:
import { defineConfig } from 'vite'
export default defineConfig({
build: {
sourcemap: true
}
})
IDE знает допустимые значения и типы свойств.
defineConfigУпрощённо функция выглядит примерно так:
function defineConfig(config) {
return config
}
Но благодаря TypeScript функция использует generics и специальные типы Vite.
Именно поэтому IDE понимает структуру объекта.
Vite позволяет экспортировать не только объект, но и функцию.
import { defineConfig } from 'vite'
export default defineConfig(() => {
return {
server: {
port: 3000
}
}
})
Такой подход нужен для динамической конфигурации.
Vite передаёт в функцию объект контекста.
import { defineConfig } from 'vite'
export default defineConfig(({ command, mode }) => {
console.log(command)
console.log(mode)
return {}
})
Доступны параметры:
| Параметр | Описание |
|---|---|
command |
текущая команда (serve или build) |
mode |
активный режим |
isSsrBuild |
SSR-сборка |
isPreview |
preview-режим |
commandcommand показывает, какая команда запущена.
vite
или:
vite dev
Тогда:
command === 'serve'
vite build
Тогда:
command === 'build'
На основе command можно разделять настройки.
import { defineConfig } from 'vite'
export default defineConfig(({ command }) => {
if (command === 'serve') {
return {
server: {
port: 3000
}
}
}
return {
build: {
minify: 'esbuild'
}
}
})
modemode определяет режим приложения.
По умолчанию:
| Команда | Mode |
|---|---|
vite |
development |
vite build |
production |
Можно запускать:
vite build --mode staging
Тогда:
mode === 'staging'
import { defineConfig } from 'vite'
export default defineConfig(({ mode }) => {
return {
define: {
__APP_MODE__: JSON.stringify(mode)
}
}
})
Одна из главных причин использования функции — разделение окружений.
import { defineConfig } from 'vite'
export default defineConfig(({ command }) => {
const isDev = command === 'serve'
return {
server: {
port: isDev ? 3000 : 8080
},
build: {
sourcemap: isDev
}
}
})
Vite предоставляет функцию loadEnv.
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd())
return {
server: {
port: Number(env.VITE_PORT)
}
}
})
loadEnvФункция загружает:
.env;.env.local;.env.production;.env.development;.env.staging.VITE_PORT=4000
Все env-переменные загружаются как строки.
Поэтому:
port: Number(env.VITE_PORT)
а не:
port: env.VITE_PORT
Vite поддерживает async-функции.
import { defineConfig } from 'vite'
export default defineConfig(async () => {
const data = await fetchSomeConfig()
return {
define: {
__CONFIG__: JSON.stringify(data)
}
}
})
Асинхронная конфигурация полезна при:
Крупные проекты часто разделяют конфигурацию на части.
// vite.base.js
export const baseConfig = {
server: {
port: 3000
}
}
// vite.dev.js
export const devConfig = {
build: {
sourcemap: true
}
}
import { defineConfig } from 'vite'
import { baseConfig } from './vite.base'
import { devConfig } from './vite.dev'
export default defineConfig({
...baseConfig,
...devConfig
})
mergeConfigVite предоставляет встроенную функцию объединения.
import { defineConfig, mergeConfig } from 'vite'
import { defineConfig, mergeConfig } from 'vite'
const baseConfig = {
server: {
port: 3000
}
}
const productionConfig = {
build: {
minify: 'terser'
}
}
export default defineConfig(
mergeConfig(baseConfig, productionConfig)
)
Vite отлично работает с TypeScript.
import { defineConfig } from 'vite'
export default defineConfig({
server: {
port: 3000
}
})
server: {
port: '3000'
}
IDE сразу покажет ошибку типа.
TypeScript помогает:
defineConfig в TypeScriptTypeScript позволяет типизировать объект вручную.
import type { UserConfig } from 'vite'
const config: UserConfig = {
server: {
port: 3000
}
}
export default config
Подход с defineConfig короче:
export default defineConfig({
server: {
port: 3000
}
})
Кроме того, функция лучше работает с infer-типами.
Обычно плагины подключаются именно внутри
defineConfig.
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()]
})
Функциональный экспорт особенно полезен для плагинов.
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig(({ command }) => {
return {
plugins: [
vue(),
command === 'serve'
? devOnlyPlugin()
: null
].filter(Boolean)
}
})
В monorepo-конфигурациях defineConfig используется
практически всегда.
Причины:
import { defineConfig } from 'vite'
import path from 'path'
export default defineConfig(({ mode }) => {
return {
root: path.resolve(__dirname, `apps/${mode}`)
}
})
Экспорт функции удобен и для библиотек.
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
entry: 'src/index.js',
name: 'MyLibrary',
fileName: 'my-library'
}
}
})
При SSR-сборке появляется isSsrBuild.
import { defineConfig } from 'vite'
export default defineConfig(({ isSsrBuild }) => {
return {
build: {
minify: !isSsrBuild
}
}
})
Параметр isPreview показывает запуск
preview-сервера.
import { defineConfig } from 'vite'
export default defineConfig(({ isPreview }) => {
return {
server: {
open: isPreview
}
}
})
Наиболее распространённый и рекомендуемый вариант:
import { defineConfig } from 'vite'
export default defineConfig(({ mode, command }) => {
const isDev = command === 'serve'
return {
server: {
port: isDev ? 3000 : 8080
},
build: {
sourcemap: isDev
},
define: {
__MODE__: JSON.stringify(mode)
}
}
})
Такой формат: