Импорт статических ресурсов

Vite рассматривает статические ресурсы как часть графа модулей приложения. Изображения, шрифты, SVG-файлы, медиафайлы и другие ассеты могут импортироваться напрямую из JavaScript, TypeScript, CSS и HTML. Во время разработки Vite отдаёт файлы через dev server практически без преобразований, а во время production-сборки оптимизирует пути, хеширует имена и перемещает ресурсы в директорию сборки.

Под статическими ресурсами обычно понимаются:

  • изображения;
  • SVG;
  • шрифты;
  • видео и аудио;
  • JSON;
  • WebAssembly;
  • текстовые файлы;
  • CSS;
  • ассеты из директории public.

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

Базовый импорт

import logo from './assets/logo.png'

const image = document.createElement('img')
image.src = logo

document.body.appendChild(image)

После импорта переменная logo содержит URL до обработанного файла.

Во время разработки значение может выглядеть так:

/assets/logo.png

После production-сборки:

/assets/logo.a1b2c3.png

Хеширование позволяет:

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

Поддерживаемые типы ресурсов

Vite автоматически обрабатывает распространённые форматы:

.png
.jpg
.jpeg
.gif
.svg
.webp
.avif
.mp4
.webm
.mp3
.woff
.woff2
.ttf

Дополнительные расширения могут подключаться через плагины или настройку Rollup.


Импорт SVG

SVG как URL

import icon from './icons/menu.svg'

console.log(icon)

Результатом будет путь к файлу.


SVG как inline-контент

Для превращения SVG в строку можно использовать суффикс ?raw.

import iconRaw from './icons/menu.svg?raw'

console.log(iconRaw)

Результат:

<svg>...</svg>

Подход полезен для:

  • динамической вставки SVG;
  • генерации иконок;
  • кастомной обработки;
  • inline-rendering.

SVG как компонент

Во многих проектах используются плагины:

  • vite-svg-loader
  • svgr
  • интеграции для React и Vue

Пример для React:

import Logo from './logo.svg?react'

export default function App() {
  return <Logo />
}

Импорт ресурсов в CSS

Vite автоматически обрабатывает пути внутри CSS.

body {
    background-image: url('./images/bg.png');
}

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

  • файл попадёт в output-директорию;
  • путь будет переписан;
  • ассет получит хеш.

Импорт шрифтов

Локальные шрифты

@font-face {
    font-family: 'Inter';
    src: url('./fonts/inter.woff2') format('woff2');
}

Vite корректно обработает:

  • копирование файла;
  • изменение пути;
  • оптимизацию output.

Импорт медиафайлов

Видео

import introVideo from './videos/intro.mp4'

const video = document.createElement('video')
video.src = introVideo
video.controls = true

document.body.appendChild(video)

Аудио

import clickSound from './audio/click.mp3'

const audio = new Audio(clickSound)
audio.play()

Импорт JSON

Vite поддерживает JSON из коробки.

import data from './data/users.json'

console.log(data)

JSON автоматически преобразуется в JavaScript-объект.


Именованный импорт JSON

import { name, version } from './package.json'

console.log(name)

Подход уменьшает объём импортируемых данных.


Импорт raw-файлов

Суффикс ?raw позволяет загружать содержимое файла как строку.

import text from './content/article.txt?raw'

console.log(text)

Применение:

  • markdown;
  • GLSL-шейдеры;
  • шаблоны;
  • SVG;
  • SQL-файлы;
  • текстовые ресурсы.

Импорт URL через ?url

Иногда требуется получить только URL ресурса без дополнительной обработки.

import fileUrl from './docs/manual.pdf?url'

Результат:

/assets/manual.xxxxx.pdf

Импорт WebAssembly

Vite поддерживает .wasm.

import init from './math.wasm'

Также доступны варианты:

import wasmUrl from './math.wasm?url'

Inline-ресурсы через Base64

Маленькие файлы могут автоматически встраиваться в bundle как Base64.

Пример:

import icon from './icon.png'

После сборки:

data:image/png;base64,...

Это уменьшает количество HTTP-запросов.


Настройка лимита inline-файлов

Параметр build.assetsInlineLimit задаёт максимальный размер файла для inline-встраивания.

import { defineConfig } from 'vite'

export default defineConfig({
    build: {
        assetsInlineLimit: 4096
    }
})

Значение указывается в байтах.


Директория public

Назначение

Папка public предназначена для файлов, которые не должны проходить через pipeline Vite.

Структура:

project/
├── public/
│   ├── robots.txt
│   ├── favicon.ico
│   └── images/

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

<img src="/images/banner.png">

Файлы:

  • копируются без изменений;
  • не хешируются;
  • сохраняют оригинальное имя.

Когда использовать public

Подходит для:

  • robots.txt;
  • manifest.json;
  • favicon;
  • sitemap;
  • файлов с фиксированным именем;
  • очень больших ассетов;
  • сторонних статических ресурсов.

Когда public использовать нежелательно

Если файл участвует в модульной системе приложения, предпочтительнее обычный импорт:

import image from './assets/photo.png'

Это обеспечивает:

  • хеширование;
  • tree-shaking;
  • оптимизацию;
  • контроль зависимостей.

Абсолютные и относительные пути

Относительный импорт

import image from './assets/picture.png'

Абсолютный путь из public

<img src="/logo.png">

Обработка ассетов во время production-сборки

Во время vite build происходит:

  1. анализ импортов;
  2. копирование ассетов;
  3. генерация хешей;
  4. переписывание путей;
  5. оптимизация структуры output.

Пример:

dist/
├── assets/
│   ├── app.a1b2.js
│   ├── logo.f3d4.png
│   └── font.e5f6.woff2

Настройка output-директории ассетов

Параметр build.assetsDir управляет каталогом ресурсов.

import { defineConfig } from 'vite'

export default defineConfig({
    build: {
        assetsDir: 'static'
    }
})

Результат:

dist/static/

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

Часто используются алиасы для упрощения импортов.

import image from '@/assets/image.png'

Настройка:

import path from 'path'
import { defineConfig } from 'vite'

export default defineConfig({
    resolve: {
        alias: {
            '@': path.resolve(__dirname, './src')
        }
    }
})

Динамический импорт ресурсов

Через new URL

Рекомендуемый способ:

const imageUrl = new URL('./img/photo.png', import.meta.url).href

Подход корректно работает:

  • в dev-режиме;
  • после сборки;
  • при SSR;
  • внутри библиотек.

Импорт набора файлов через import.meta.glob

Загрузка изображений

const images = import.meta.glob('./gallery/*.png', {
    eager: true
})

console.log(images)

Vite создаст объект:

{
  './gallery/1.png': Module,
  './gallery/2.png': Module
}

Lazy-загрузка ресурсов

const modules = import.meta.glob('./pages/*.js')

Файлы загружаются только при необходимости.


Обработка CSS-ассетов

Vite автоматически анализирует:

  • url()
  • @import
  • вложенные зависимости

Пример:

.hero {
    background: url('./hero.webp');
}

Asset Graph

Одной из важных особенностей Vite является построение графа зависимостей ресурсов.

Пример цепочки:

main.js
 └── style.css
      └── font.woff2

Vite отслеживает все связи и корректно обновляет ресурсы через HMR.


HMR и статические ресурсы

При изменении:

  • изображения;
  • CSS;
  • SVG;
  • шрифтов;

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

Это особенно важно при разработке интерфейсов.


Кэширование ассетов

Production-сборка использует content hash:

logo.a1b2c3.png

Изменение файла приводит к изменению имени, благодаря чему браузер автоматически загружает новую версию.


Ограничения импорта

Vite работает через ES Modules, поэтому импорт должен быть анализируемым.

Корректно:

import img from './img/photo.png'

Проблемно:

import img from dynamicVariable

Для динамических путей рекомендуется:

new URL(path, import.meta.url)

или:

import.meta.glob()

Импорт ресурсов в TypeScript

TypeScript может требовать декларации модулей.

Пример:

declare module '*.png' {
    const value: string
    export default value
}

Однако большинство шаблонов Vite уже содержат необходимые типы.


Роль Rollup в обработке ассетов

Production-сборка Vite основана на Rollup.

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

  • финальную упаковку;
  • asset pipeline;
  • code splitting;
  • оптимизацию output.

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

Ресурсы могут подключаться напрямую:

const image = 'https://cdn.example.com/banner.png'

Но локальный импорт через Vite даёт:

  • контроль версий;
  • оптимизацию;
  • удобство разработки;
  • автоматическую обработку путей.

SSR и импорт ассетов

В SSR-режиме Vite генерирует специальные manifest-файлы, связывающие серверный код и production-ассеты.

Это особенно важно для:

  • React SSR;
  • Vue SSR;
  • middleware-архитектур;
  • Node.js-rendering.

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

src/
├── assets/
│   ├── images/
│   ├── fonts/
│   ├── icons/
│   └── videos/
├── components/
├── styles/
└── main.js

Практика разделения ресурсов

Часто применяется следующая схема:

assets/
├── images/
├── icons/
├── fonts/
├── audio/
├── video/
└── svg/

Это упрощает:

  • поддержку проекта;
  • навигацию;
  • автоматизацию;
  • масштабирование frontend-архитектуры.