Обработка изображений и шрифтов

Rollup изначально ориентирован на JavaScript-модули и не предоставляет встроенной полноценной системы обработки бинарных ассетов. Работа с изображениями, шрифтами и другими статическими файлами реализуется через плагины, каждый из которых решает конкретный сценарий: инлайнинг, копирование, преобразование в строки или генерацию отдельных файлов в выходной сборке.


Общая модель работы с ассетами в Rollup

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

  • импорт файла как URL
  • преобразование в base64 (data URI)
  • копирование в выходной каталог
  • преобразование в модуль (строка, объект метаданных)

Ключевой механизм — обработка import нестандартных расширений через плагины.


Обработка изображений

Подключение изображений как модулей

Типичный импорт:

import logo fr om './assets/logo.png';

Без дополнительных плагинов Rollup не сможет обработать такой импорт. Для этого используется плагин:

  • @rollup/plugin-url

Плагин @rollup/plugin-url

Основная задача — конвертация файлов в URL или base64.

Установка

npm install @rollup/plugin-url -D

Базовая конфигурация

import url from '@rollup/plugin-url';

export default {
  input: 'src/index.js',
  output: {
    dir: 'dist',
    format: 'esm'
  },
  plugins: [
    url({
      lim it: 10 * 1024,
      include: ['**/*.png', '**/*.jpg', '**/*.jpeg', '**/*.svg', '**/*.gif'],
      emitFiles: true,
      fileName: '[name]-[hash][extname]'
    })
  ]
};

Поведение плагина

  • Файлы меньше limit преобразуются в base64
  • Файлы больше limit копируются в output directory
  • Импорт заменяется строкой URL

Инлайнинг изображений (Base64)

Механизм инлайнинга уменьшает количество HTTP-запросов, но увеличивает размер JS-бандла.

Пример результата:

const logo = "data:image/png;base64,iVBORw0KGgoAAAANS...";

Когда применяется инлайнинг

  • иконки UI
  • небольшие декоративные изображения
  • критические ресурсы первого экрана

Вынос изображений в файлы

При отключённом инлайнинге или превышении лимита происходит генерация файлов:

dist/
  assets/
    logo-a1b2c3.png

Импорт становится строкой:

const logo = "/assets/logo-a1b2c3.png";

Оптимизация изображений в цепочке Rollup

Rollup не выполняет оптимизацию изображений сам по себе. Используются дополнительные плагины:

  • rollup-plugin-imagemin — сжатие PNG/JPEG/SVG
  • внешние пайплайны (sharp, imagemin CLI)

Пример подключения:

import { imagemin } fr om 'rollup-plugin-imagemin';

imagemin({
  plugins: [
    require('imagemin-pngquant')(),
    require('imagemin-mozjpeg')({ quality: 75 })
  ]
});

Работа с SVG

SVG может обрабатываться тремя способами:

1. Как URL (через @rollup/plugin-url)

import icon from './icon.svg';

Результат — строка URL.


2. Как inline-строка

При отключении emitFiles:

url({
  include: ['**/*.svg'],
  lim it: Infinity
});

SVG становится строкой:

const icon = "<svg xmlns=...>...</svg>";

3. Как компонент (через SVGR)

Используется плагин:

  • @svgr/rollup
import svgr fr om '@svgr/rollup';

export default {
  plugins: [svgr()]
};

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

import Icon from './icon.svg';

export default () => <Icon />;

Обработка шрифтов

Шрифты требуют особого подхода из-за CSS-интеграции.

Поддерживаемые форматы

  • .woff
  • .woff2
  • .ttf
  • .otf

Подключение через @rollup/plugin-url

Шрифты обрабатываются аналогично изображениям:

url({
  include: ['**/*.woff', '**/*.woff2', '**/*.ttf'],
  lim it: 0,
  fileName: 'fonts/[name]-[hash][extname]'
});

Использование через CSS @font-face

Наиболее распространённый сценарий:

@font-face {
  font-family: "Inter";
  src: url("./fonts/Inter-Regular.woff2") format("woff2"),
       url("./fonts/Inter-Regular.woff") format("woff");
  font-weight: 400;
  font-style: normal;
}

Далее CSS подключается через:

  • rollup-plugin-postcss

rollup-plugin-postcss и шрифты

npm install rollup-plugin-postcss -D

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

import postcss from 'rollup-plugin-postcss';

postcss({
  extract: true,
  minimize: true
});

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

  • шрифты копируются через url-плагины
  • CSS генерирует ссылки на итоговые файлы
  • возможно хеширование путей

Организация структуры ассетов

Рекомендуемая структура:

src/
  assets/
    images/
    fonts/
    icons/

Сборка:

dist/
  assets/
    images/
    fonts/

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

Для предотвращения кеширования используется [hash]:

fileName: '[name]-[hash][extname]'

Результат:

logo-8f3a91.png
Inter-4c9d2b.woff2

Управление публичным путём (publicPath)

При размещении сборки на CDN или подкаталоге важно корректно задать базовый путь:

output: {
  dir: 'dist',
  format: 'esm',
  assetFileNames: 'assets/[name]-[hash][extname]',
  entryFileNames: 'js/[name]-[hash].js',
  chunkFileNames: 'js/[name]-[hash].js'
}

Дополнительно может использоваться:

url({
  publicPath: 'https://cdn.example.com/'
});

Копирование ассетов без трансформации

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

  • rollup-plugin-copy
npm install rollup-plugin-copy -D
import copy from 'rollup-plugin-copy';

copy({
  targets: [
    { src: 'public/fonts/*', dest: 'dist/fonts' }
  ]
});

Встраивание ассетов в JS-модули

Некоторые плагины позволяют импортировать ассеты как строки:

import template from './template.html';

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


Типовые проблемы при работе с изображениями и шрифтами

Потеря путей после сборки

Причина — отсутствие fileName или publicPath.


Дублирование ассетов

Возникает при:

  • множественных импортax одного файла
  • отключённом кэшировании плагина

Некорректная работа CSS шрифтов

Причины:

  • неверный относительный путь
  • отсутствие обработки CSS через плагин
  • несовпадение форматов woff/woff2

Оптимизационные стратегии

Разделение ассетов по типам

  • изображения → images/
  • шрифты → fonts/
  • иконки → inline SVG

Контроль лимита инлайнинга

  • маленькие файлы → base64
  • большие → отдельные ресурсы

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

Ассеты выносятся на отдельный домен:

publicPath: 'https://cdn.site.com/assets/'

Минимизация размера шрифтов

  • использование woff2
  • subset (удаление лишних символов)
  • lazy-loading шрифтов через CSS

Интеграция с современными сборочными пайплайнами

Rollup часто используется как часть более сложных систем:

  • библиотечные сборки
  • дизайн-системы
  • UI-компоненты

В таких сценариях изображения и шрифты:

  • либо эмитятся как артефакты библиотеки
  • либо остаются внешними зависимостями

Связка с TypeScript и декларациями

Для корректного импорта ассетов используются декларации:

declare module '*.png' {
  const src: string;
  export default src;
}
declare module '*.woff2' {
  const src: string;
  export default src;
}

Поведение в разных форматах сборки

ESM

import logo from './logo.png';

Возвращает строку URL.


CommonJS

const logo = require('./logo.png');

Поведение зависит от плагина и транспиляции.


IIFE (браузерный бандл)

Ассеты обычно инлайнуются или копируются в отдельную директорию с относительными ссылками.