Как настроить Storybook для Next.js: CSS и изображения
Storybook позволяет разрабатывать UI-компоненты в изоляции, но по умолчанию требует настройки CSS/Sass и обработки изображений Next.js. В статье — пошаговая инструкция: инициализация Storybook, подключение глобальных стилей, поддержка Sass, раздача папки public и применение свойства unoptimized для компонентов next/image. Внизу — чек-листы, критерии приёмки, альтернативы и часто задаваемые вопросы.

Storybook — мощный инструмент для разработки UI в изоляции. Он помогает создавать и тестировать компоненты без запуска всего приложения. Если вы уже работали с Storybook и Next.js, заметите: нужно правильно настроить обработку CSS и изображений. Этот процесс иногда вводит в заблуждение; ниже — простые практические шаги, которые помогут пройти весь путь.
Начало: подготовка проекта Next.js
Если у вас ещё нет проекта на Next.js, создайте новый по официальному руководству Getting Started на сайте Next.js. Коротко: создайте проект, установите зависимости и убедитесь, что приложение запускается локально.
Инициализация Storybook
Запустите в терминале команду инициализации Storybook:
npx sb init --builder webpack5Эта команда обнаружит тип проекта, установит необходимые пакеты и создаст примерные сторис.
Настройка CSS в Storybook
Первое — подключить глобальный CSS в preview.js, чтобы все сторис наследовали общие стили.
Глобальные стили
Глобальные стили применяются ко всему приложению. Можно импортировать файл в каждую сторис вручную, но это неудобно и ошибочно при масштабировании. Лучше импортировать глобальные стили в файл .storybook/preview.js, где хранятся общие настройки Storybook.
В начале .storybook/preview.js добавьте:
import "../styles/globals.css";Это обеспечит единообразие стилей во всех сторис и избавит от повторных импортов.
Важно: если вы используете CSS Modules одновременно с глобальными стилями, оставьте соглашения по именованию и область применения стилей неизменными, чтобы избежать конфликтов.
Поддержка Sass в Storybook для Next.js
По умолчанию Storybook не имеет встроенной поддержки Sass (.scss/.sass). Нужно расширить webpack-конфигурацию и установить загрузчики:
npm i -D style-loader css-loader sass-loaderРоль пакетов:
- style-loader — внедряет CSS в DOM.
- css-loader — обрабатывает import и url() в CSS как import/require и разрешает их.
- sass-loader — компилирует SCSS/Sass в CSS.
Чтобы настроить загрузчики, добавьте в .storybook/main.js следующий код:
const path = require('path');
module.exports = {
// other configurations
webpackFinal: async (config) => {
config.module.rules.push(
{
test: /\.s(a|c)ss$/,
include: path.resolve(__dirname, '../'),
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
auto: true,
localIdentName: '[name]__[local]--[hash:base64:5]',
},
},
},
'sass-loader'
],
},
);
return config;
}
}После этого Sass станет доступен в Storybook. Проверьте, что ваши пути include покрывают директории с компонентами и стилями.
Раздача папки public и деоптимизация изображений Next.js
Next.js использует оптимизацию изображений через компонент next/image. В Storybook, работающем вне окружения Next.js, это часто создаёт сложности. Проще деоптимизировать изображения в сторис — тогда компонент будет рендериться без серверной оптимизации.
Сначала нужно служить статические файлы из папки public в Storybook. Это можно сделать через npm-скрипты в package.json или через настройку staticDirs в .storybook/main.js.
В package.json обновите скрипты Storybook:
"scripts": {
"storybook": "start-storybook -p 6006 -s ./public",
"build-storybook": "build-storybook -s public"
}Или добавьте в .storybook/main.js:
module.exports = {
// other configurations
"staticDirs": [ "../public" ],
}После того как папка public доступна в Storybook, примените свойство unoptimized к компоненту next/image, используемому в сторис. Для этого в .storybook/main.js (или в .storybook/preview.js) можно сделать переопределение:
import * as NextImage from "next/image";
const OriginalNextImage = NextImage.default;
Object.defineProperty(NextImage, "default", {
configurable: true,
value: (props) => (
),
});Этот трюк делает так, что в контексте Storybook компонент next/image будет отрисовываться без серверной оптимизации, что упрощает работу с изображениями и избавляет от ошибок, связанных с отсутствием Next.js runtime.
Примечание: не применяйте unoptimized в продакшн-режиме вашего приложения — это только для сторис и локальной разработки.
Практическая мини-методология: шаги для настройки
- Убедитесь, что проект Next.js работает локально.
- npx sb init –builder webpack5.
- Импортируйте ../styles/globals.css в .storybook/preview.js.
- Установите style-loader, css-loader, sass-loader и добавьте правило в webpackFinal.
- Раздайте public через staticDirs или флаг -s в скрипте start-storybook.
- Переопределите next/image, добавив unoptimized в .storybook конфиг.
- Протестируйте сторис — проверьте стили и изображения.
- Добавьте критерии приёмки и автоматические тесты визуальной регрессии при необходимости.
Чек-листы по ролям
Разработчик:
- Инициировать Storybook и подтвердить запуск.
- Подключить глобальные стили в preview.js.
- Настроить загрузчики для Sass в .storybook/main.js.
- Убедиться, что public раздаётся и изображения доступны.
Дизайнер:
- Проверить, что компоненты соответствуют макету.
- Тестировать вариации размеров и состояний компонентов.
QA:
- Проверить рендеринг изображений и альтернативный текст.
- Провести визуальные регрессии (при наличии инструментов).
Критерии приёмки
- Все сторис загружаются без ошибок в консоли.
- Глобальные стили применяются ко всем компонентам.
- SCSS-файлы корректно компилируются и применяются.
- Изображения в сторис отображаются корректно (без 404).
- Для next/image используется unoptimized в Storybook, но нет изменений в продакшн-билде.
Когда такой подход не сработает (ограничения)
- Если вы используете серверную оптимизацию изображений, зависящую от runtime (например, кастомные декодеры, AVIF конверсии на лету), простое unoptimized не воспроизведёт поведение продакшна.
- Если у вас сложный кастомный webpack-конфиг Next.js, требующий специфичных плагинов, вам нужно синхронизировать эти плагины и в Storybook.
- Если компонент рассчитывает размеры по window/viewport во время SSR, поведение в Storybook может отличаться.
Альтернативные подходы
- Мокать компонент next/image простым img-обёрткой в stories, вместо применения unoptimized.
- Использовать Chromatic или визуальную регрессию для тестирования компонентов в окружении CI.
- Переход на builder Vite для Storybook (если проект поддерживает), что может упростить некоторые настройки.
Сценарии тестирования и критерии приёмки для изображений
Тесты (ручные/автоматические):
- Открыть сторис с компонентом, содержащим изображение, и убедиться, что src корректен и загружен.
- Проверить наличие и содержимое alt-атрибута (валидность для доступности).
- Сменить размеры в панели и убедиться, что изображение адаптируется.
Критерии приёмки:
- Никаких 404 при загрузке изображений.
- Alt-атрибут присутствует для всех контентных изображений.
- При переключении состояний компонент не ломает лэйаут.
Совместимость и миграция
- Паттерн с переопределением next/image работает для большинства версий Next.js, но поведение могло измениться в крупных релизах — следите за официальной документацией при обновлении Next.js.
- Если вы мигрируете с Webpack 4 на Webpack 5, проверьте соответствие плагинов и loaders.
Пример принятого рабочего набора (cheat sheet)
- package.json scripts:
"storybook": "start-storybook -p 6006 -s ./public",
"build-storybook": "build-storybook -s public"- .storybook/preview.js:
import "../styles/globals.css";
// можно добавить глобальные декораторы и параметры Storybook тут- .storybook/main.js: правило для Sass + staticDirs либо staticDirs в корне конфига.
Короткая галерея крайних случаев
- Большие изображения (несжатые) в public — приводят к медленной загрузке в Storybook; используйте оптимизированные версии для разработческих сторис.
- Компоненты, зависящие от process.env, — убедитесь, что необходимые переменные окружения заданы для Storybook.
FAQ
Нужно ли добавлять unoptimized в продакшн?
Нет. unoptimized используется только для Storybook и локальной разработки. В продакшне оставьте оптимизацию Next.js для лучших показателей загрузки.
Можно ли не использовать unoptimized и как альтернативу — мокать next/image?
Да. Можно заменить next/image на простой img в сторис или написать небольшой wrapper, который в Storybook возвращает img, а в приложении — next/image.
Что делать, если SCSS не применяется в компоненте?
Проверьте include-путь в webpackFinal, убедитесь, что правило срабатывает для папки с компонентами. Также убедитесь, что расширения файлов корректны (.scss/.sass).
Краткое резюме
Storybook улучшает разработку компонентов, но требует настройки CSS и обработки изображений в Next.js. Подключение глобальных стилей в .storybook/preview.js, добавление поддержки Sass через style/css/sass-loader и раздача public с применением unoptimized для next/image обычно решают большинство проблем. Используйте чек-листы и критерии приёмки для стабильности и масштабирования.
Важно: тестируйте сторис и не переносите дев-конфигурации (как unoptimized) в продакшн.
Похожие материалы
Градиенты в Canva: добавить и настроить
Ошибка Disabled accounts can't be contacted в Instagram
Генерация случайных чисел в Google Sheets
Прокручиваемые скриншоты в Windows 11
Как установить корпусной вентилятор в ПК