Настройка Storybook для Next.js: CSS и изображения

Быстрая настройка Storybook для проекта на Next.js: импортируйте глобальные стили в .storybook/preview.js, добавьте загрузчики для Sass в .storybook/main.js и отключите оптимизацию Next.js Image в среде Storybook. Ниже — пошаговое руководство, чеклисты и рекомендации по отладке.
Storybook — мощный инструмент для разработки UI-компонентов в изоляции. Он позволяет создавать и тестировать компоненты без запуска всего приложения. При интеграции со Next.js важно корректно настроить обработку CSS, Sass и изображений, чтобы истории выглядели и работали так же, как в приложении.
Быстрый обзор шагов
- Инициализировать Storybook в проекте.
- Импортировать глобальные стили в .storybook/preview.js.
- Установить и настроить загрузчики для Sass (style-loader, css-loader, sass-loader).
- Обслуживать папку public в Storybook.
- Включить prop unoptimized для next/image в окружении Storybook.
Инициализация Storybook
Если Storybook ещё не добавлен, выполните в терминале:
npx sb init --builder webpack5Эта команда обнаружит тип проекта, установит зависимости и создаст примерные истории.
Подключение глобальных стилей
Чтобы глобальные стили из Next.js применялись и в историях Storybook, импортируйте их в файл, отвечающий за предварительную загрузку конфигурации Storybook.
Импорт глобальных стилей
Добавьте в начало файла .storybook/preview.js импорт глобального CSS:
import "../styles/globals.css";Это гарантирует, что переменные CSS, базовые reset-правила и общие классы будут доступны во всех историях, без необходимости импортировать стили в каждой истории вручную.
Важно: если в проекте используются CSS Modules, дополнительно проверьте конфигурацию css-loader (ниже) чтобы модули работали корректно.
Настройка Sass для Storybook
Storybook по умолчанию не включает поддержку Sass. Установите необходимые загрузчики:
npm i -D style-loader css-loader sass-loaderКоротко о назначении пакетов:
- style-loader — внедряет CSS в DOM во время работы Storybook.
- css-loader — обрабатывает @import и url() как импорты, разрешая зависимости CSS.
- sass-loader — компилирует SCSS/Sass в CSS.
Добавьте конфигурацию в .storybook/main.js, чтобы Webpack обрабатывал файлы .scss/.sass:
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;
}
}После этого вы сможете импортировать .scss/.sass-файлы в компонентах и историях.
Обслуживание папки public и отключение оптимизации изображений
Next.js использует компонент next/image с оптимизацией изображений. В Storybook, который запускается вне окружения Next.js, эта оптимизация может ломать отображение или вызывать ошибки. Решение — подготовить Storybook так, чтобы он обслуживал папку public и применять prop unoptimized к компоненту Image.
Вариант 1: Обслуживание public через package.json
В package.json добавьте параметры запуска Storybook, чтобы передавать статические файлы:
"scripts": {
"storybook": "start-storybook -p 6006 -s ./public",
"build-storybook": "build-storybook -s public"
}Вариант 2: Обслуживание через staticDirs в .storybook/main.js
module.exports = {
// other configurations
"staticDirs": [ "../public" ],
}Принудительное отключение оптимизации next/image в Storybook
Добавьте в конфигурацию Storybook код, который заменяет поведение компонента next/image, передавая prop unoptimized по умолчанию:
import * as NextImage from "next/image";
const OriginalNextImage = NextImage.default;
Object.defineProperty(NextImage, "default", {
configurable: true,
value: (props) => (
),
});Такой подход гарантирует, что все истории, где используется next/image, будут отображать изображения без серверной оптимизации Next.js.
Примеры когда такой подход не работает
- Если компонент ожидает специфичного поведения оптимизатора (например, srcSet, автоматический ресайз) — отключённая оптимизация может привести к несподручному отображению на адаптивных точках останова.
- Если проект использует внешние домены для картинок, нужно добавить соответствующие разрешения или проксирование при работе с staticDirs.
Альтернативы: использовать обычный img-тег в историях или написать небольшую mock-обёртку для next/image, которая симулирует поведение оптимизатора.
Чеклисты по ролям
Developer
- Инициализировал Storybook и запустил локально.
- Добавил import глобальных стилей в .storybook/preview.js.
- Настроил sass-loader и css-loader в .storybook/main.js.
- Применил unoptimized для next/image.
Designer
- Проверил визуальные соответствия компонентов в Storybook.
- Протестировал адаптивность и шрифты.
QA
- Убедился, что stories покрывают критические состояния компонентов.
- Проверил отображение изображений и отсутствие ошибок в консоли.
DevOps
- Добавил сборку build-storybook в CI.
- Убедился, что статические файлы корректно развёрнуты на staging/production.
Мини-методология по добавлению нового компонента в Storybook
- Создайте компонент в src/components.
- Напишите stories в соответствующей папке stories или рядом с компонентом (Component.stories.jsx).
- Проверьте, что глобальные стили и зависимости работают в режиме Storybook.
- Добавьте тесты визуальной регрессии (если используется Percy, Chromatic и т.п.).
- Пройдите чеклист ролей.
Критерии приёмки
- Все истории доступны и запускаются без ошибок в консоли.
- Компоненты визуально совпадают с реализацией в приложении (шрифты, отступы, цвета).
- Изображения отображаются корректно, нет 404 при запросе из сборки Storybook.
Руководство по устранению неполадок
Проблема: CSS не применяется в историях
- Проверьте, что импорт глобальных стилей указан в .storybook/preview.js.
- Убедитесь, что путь к файлу верный и файл входит в include в конфигурации Webpack.
Проблема: Ошибки при импорте .scss
- Убедитесь, что установлены style-loader, css-loader и sass-loader.
- Проверьте, что правило теста в .storybook/main.js покрывает нужные папки проекта.
Проблема: next/image вызывает ошибку или не показывает изображение
- Проверьте, что staticDirs или флаг -s ./public настроены и public доступен.
- Убедитесь, что вы применили unoptimized, либо заменили next/image на mock в Storybook.
Тесты приёмки
- Локально запустите npm run storybook и откройте http://localhost:6006.
- Пройдите основные истории, проверьте отображение изображений и отсутствие ошибок.
Советы и нюансы
- Если вы используете TypeScript, добавьте соответствующие типы для импорта CSS/Sass, чтобы избежать ошибок компиляции.
- Для CSS Modules оставьте опцию modules.auto: true — это позволяет использовать как модули, так и глобальные файлы без конфликтов.
- Для интеграции с инструментами визуального тестирования (Chromatic) убедитесь, что build-storybook собирает статические asset-файлы.
Короткий справочный блок
- Команды: npx sb init, npm run storybook, npm run build-storybook
- Файлы конфигурации: .storybook/main.js, .storybook/preview.js, package.json
1‑строчный глоссарий
- Storybook — среда для разработки UI-компонентов в изоляции.
- next/image — компонент Next.js для оптимизации изображений.
- unoptimized — проп next/image, отключающий серверную оптимизацию.
Итог
Настройка Storybook для Next.js требует трёх ключевых шагов: подключение глобальных стилей, добавление поддержки Sass и обработка изображений (обслуживание public и применение unoptimized). Следуя указанной последовательности и проверочным спискам, вы добьётесь консистентности компонентов между Storybook и приложением.
Полезно сохранить в репозитории: файл .storybook/preview.js с импортом глобальных стилей, .storybook/main.js с webpackFinal и staticDirs, а также npm-скрипты для запуска и сборки Storybook.
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента