Storybook – это инструмент для разработки и тестирования UI-компонентов в изоляции. С его помощью вы можете просматривать и документировать компоненты вашего приложения, не запуская само приложение. В этом руководстве рассмотрим, как настроить Storybook в проекте на Quasar 2 (фреймворке на базе Vue 3) с поддержкой TypeScript и Composition API. Мы пройдем все шаги – от создания проекта Quasar до запуска Storybook – и уделим внимание интеграции компонентов Quasar, настройке плагинов, тем и решению возможных ошибок.
1. Создание проекта на Quasar 2 (Vue 3 + TypeScript)
Если у вас уже есть готовый проект на Quasar 2, можете перейти к следующему шагу. В противном случае создадим новый проект:
- Установите Quasar CLI (если не установлен): Quasar предоставляет CLI для быстрой генерации проектов. Установите его глобально командой:
npm install -g @quasar/cli (Можно использовать Yarn: yarn global add @quasar/cli.) - Создайте новый проект: Выполните команду создания проекта Quasar:
quasar create my-quasar-app
(Либо без глобального CLI: yarn create quasar или npm init quasar — результат аналогичен.) - Выберите опции проекта: Во время создания утилита спросит ряд вопросов о конфигурации. Для нашего случая рекомендуются следующие ответы:
Quasar версии 2 (основан на Vue 3).
TypeScript – включаем поддержку TypeScript.
Quasar CLI с Vite – выбираем сборщик Vite (он быстрее и современнее Webpack, и мы будем его использовать вместе со Storybook).
CSS-препроцессор – можно выбрать SCSS (Sass) для примера.
Стиль компонентов Vue – Composition API с синтаксисом <script setup>.
Остальные настройки (например, Pinia, Vue-i18n) – по желанию. Для простоты в этом руководстве они не обязательны.Например, в одном из примеров конфигурация выбрана так: TypeScript, Quasar 2, Vite, SCSS, Pinia, Vue-i18n и Composition API с <script setup>. Не переживайте, если вы не уверены в каких-то опциях – всегда можно принять значения по умолчанию. - Установите зависимости и запустите проект: Перейдите в папку проекта (cd my-quasar-app) и установите пакеты:
npm install
Затем убедитесь, что проект запускается:
quasar dev или npx quasar dev
Проект должен скомпилироваться и открыться в браузере (по умолчанию http://localhost:9000). Теперь у нас есть рабочее Quasar-приложение на Vue 3 + TypeScript.
Примечание: Если вы добавили поддержку TypeScript, Quasar сгенерирует файл tsconfig.json с необходимыми настройками, а компоненты можно писать с использованием <script lang="ts">. Мы будем использовать Composition API, поэтому примеры компонентов будут через <script setup>.
2. Установка и настройка Storybook (Vue 3 + TypeScript)
Далее интегрируем Storybook в наш Quasar-проект:
- Инициализируйте Storybook: В корне проекта запустите команду:
npx storybook@latest init
Эта команда добавит необходимые зависимости и создаст директорию .storybook/ с базовой конфигурацией. В процессе вам могут быть заданы вопросы – выберите вариант Vue 3 (если запрашивается фреймворк) и согласитесь на использование TypeScript, если будет предложено. В результате Storybook настроится для Vue 3 автоматически.
Совет: Также можно указать тип прямо в команде, например:
npx sb init --type vue3
Это явно установит поддержку Vue 3. В новых версиях Storybook, если ваш проект на Vite, Storybook может попытаться использовать Vite в качестве сборщика. - Установка Vite (если требуется): Quasar CLI (Vite) скрывает реализацию Vite внутри себя, поэтому в package.json вашего проекта может не быть явной зависимости на vite. Storybook же ожидает, что Vite установлен (если мы используем его как bundler). Если при запуске Storybook вы получили ошибку, что не найден vite или аналогичные проблемы при сборке, просто установите Vite вручную как dev-зависимость:
npm install -D vite
В одном из примеров после инициализации Storybook появлялась ошибка, связанная с Vite, и решение было именно установить vite локально. - Проверка запуска: Попробуйте запустить Storybook командой:
npm run storybook (Script storybook уже должен быть добавлен в ваш package.json.) Если всё настроено правильно, сборка запустится и Storybook откроется на http://localhost:6006. Однако, возможно, на данном этапе вы встретите некоторые ошибки или проблемы (мы их сейчас устраним). - Настройка сборщика (Vite vs Webpack): По умолчанию Storybook для Vue 3 мог быть настроен на Webpack. Мы же хотим использовать Vite, чтобы ближе соответствовать окружению Quasar и упростить конфигурацию. Убедитесь, что в файле конфигурации .storybook/main.js выбран Vite:
В Storybook 7+ конфигурация для Vue 3 + Vite указывается как:
framework: {
name: '@storybook/vue3-vite',
options: {}
},
(Если у вас Storybook 6.x, вместо этого может использоваться core: { builder: "webpack5" } – в таком случае нужно переключиться на Vite-билдер, установив пакет @storybook/builder-vite и изменив конфиг. Рассмотрим актуальный подход для Storybook 7.)
Откройте .storybook/main.js (или .ts). Если там указано framework: '@storybook/vue3' или явно указан Webpack, замените на Vite-версию. Например, для Storybook 7 нужно установить пакет:
npm install -D @storybook/vue3-vite @storybook/builder-vite
И изменить конфиг:
// .storybook/main.js
module.exports = {
stories: ['../src/**/*.stories.@(ts|tsx|js|jsx|mdx)'],
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
framework: {
name: '@storybook/vue3-vite',
options: {}
}
// ...остальные настройки...
}
В приведенном фрагменте мы подключили Vite-билдер для Vue3. Storybook теперь будет использовать Vite при запуске. - Поддержка TypeScript в конфиге Storybook: Если вы предпочитаете, можете переименовать файлы конфигурации Storybook в .ts (например, main.ts, preview.ts) для полной поддержки TypeScript. Storybook 7 умеет читать .ts-файлы конфигурации, но для этого может понадобиться Babel-пресет. Проще всего создать файл .babelrc в корне проекта со следующим содержимым:
{
"presets": [
"@babel/preset-env",
"@babel/preset-typescript"
]
}
Это нужно, чтобы Storybook смог парсить .ts файлы конфига. Однако, если не хотите усложнять, можете оставить конфигурационные файлы в JS – на работу Storybook это не повлияет. - Добавление алиасов (alias) из Quasar: Quasar-проекты обычно используют удобные алиасы для путей. Например, Quasar по умолчанию может настроить алиас src или @ на папку src. Если в коде компонентов вы импортируете модули по алиасу, Storybook о них не знает и при запуске выдаст ошибки, что не может резолвить модули. Мы должны вручную определить эти алиасы в конфигурации Storybook:
Для Vite-билдера можно использовать функцию viteFinal в main.ts для добавления алиасов:
import { StorybookConfig } from '@storybook/vue3-vite';
import { resolve } from 'path';
const config: StorybookConfig = {
// ... другие настройки ...
async viteFinal(config) {
// Добавляем алиасы путей, если они еще не определены
if (config.resolve) {
config.resolve.alias = {
...config.resolve.alias,
'src': resolve(__dirname, '../src'), // алиас 'src' -> папка src
'@': resolve(__dirname, '../src') // алиас '@' -> папка src (если вы используете '@')
};
}
return config;
}
};
export default config;
Теперь Storybook сможет понимать импорты вида import Something from 'src/components/Component.vue' или '@/components/Component.vue'.
В примере мы добавили алиас src, так как Quasar CLI часто задает его по умолчанию. При необходимости добавьте и другие, например, алиас на components или другие директории, используемые в ваших импортах.
На этом этапе Storybook установлен и базово настроен. Далее интегрируем Quasar, чтобы в Storybook можно было использовать компоненты Quasar-фреймворка.
3. Интеграция компонентов Quasar в Storybook
Чтобы компоненты Quasar (например, <q-btn>, <q-card> и т.д.) корректно работали и отображались внутри Storybook, нужно выполнить два основных шага: зарегистрировать Quasar как плагин в приложении Vue, которое использует Storybook, и подключить стили Quasar (CSS темы, иконки и прочее).
Откройте файл .storybook/preview.js (или preview.ts, если вы его переименовали):
- Импорт стилей Quasar: Добавьте импорты необходимых CSS. Минимально нужны основные стили Quasar и выбранные наборы иконок/шрифтов:
import '@quasar/extras/roboto-font/roboto-font.css'; // Шрифт Roboto (по умолчанию в Quasar)
import '@quasar/extras/material-icons/material-icons.css'; // Иконки Material Icons (если используете их)
// import '@quasar/extras/fontawesome-v5/fontawesome-v5.css'; // Пример: другие наборы иконок (опционально)
import 'quasar/dist/quasar.css'; // Основной CSS-файл Quasar
Эти строки подключат стандартный стиль Quasar и ресурсы. Roboto-шрифт и Material Icons идут по умолчанию в свежем проекте Quasar (если вы выбрали Material Icons при создании).
При необходимости подключите и другие Quasar Extras – например, анимации (как в примере ниже) или другие иконки.
Регистрация Quasar-плагина: После стилей импортируйте сам Quasar и зарегистрируйте его в Vue:
import { app } from '@storybook/vue3'; // Vue-приложение внутри Storybook
import { Quasar, Notify, Dialog } from 'quasar';
// Зависимости Quasar: можно импортировать отдельные сервисы/плагины (Notify, Dialog - примеры)
app.use(Quasar, {
config: { }, // глобальная конфигурация Quasar (напр. { brand: { primary: '#E46262' }, dark: true } )
plugins: { Notify, Dialog } // регистрация необходимых плагинов Quasar
});
Здесь мы используем глобальный Vue-приложение Storybook (app) и устанавливаем Quasar как плагин. Передаем пустой config (можно настроить тему, цвета, включить темную тему и пр. через config, если нужно) и перечисляем Quasar-плагины, которые хотим использовать. Важно: Добавьте сюда все Quasar-плагины, которые вы используете в своих компонентах. Например, если в компонентах вы вызываете this.$q.notify(...), нужно подключить Notify, если используете диалоги Dialog.create(), подключите Dialog и т.д.
После этих изменений файл preview.js будет выглядеть примерно так (сокращенно):
import '@quasar/extras/roboto-font/roboto-font.css';
import '@quasar/extras/material-icons/material-icons.css';
import 'quasar/dist/quasar.css';
import { app } from '@storybook/vue3';
import { Quasar, Notify, Dialog } from 'quasar';
// Регистрация Quasar
app.use(Quasar, { config: {}, plugins: { Notify, Dialog } });
// Параметры Storybook (actions и controls остаются как были по шаблону)
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: { ... }
};
Storybook теперь знает о компонентах Quasar – мы подключили все необходимые ресурсы. При рендеринге историй (stories) Quasar-компоненты будут глобально зарегистрированы, а стили применены.
Можно сохранить изменения и перезапустить Storybook (npm run storybook). Если всё сделано правильно, dev-сервер запустится без ошибок. Мы готовы писать истории для компонентов.
4. Добавление примера истории для компонента (кнопки)
Для демонстрации создадим простой компонент кнопки и историю для него. Предположим, в нашем проекте есть компонент MyButton.vue, который оборачивает Quasar-кнопку <q-btn> с некоторыми пропсами.
Создайте компонент кнопки: src/components/MyButton.vue:
<template>
<!-- Используем Quasar QBtn как основу кнопки -->
<q-btn :label="label" :color="color" @click="onClick" />
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue';
// Определяем входные пропсы компонента с типизацией
interface Props {
label: string;
color: string;
}
const props = defineProps<Props>();
const emits = defineEmits<{ (e: 'click'): void }>();
// Обработчик клика, эмитит событие 'click'
function onClick() {
emits('click');
}
</script>
В этом компоненте мы использовали Composition API (<script setup>): определили пропсы label и color через defineProps с интерфейсом Props (TypeScript) и событие click через defineEmits. Компонент отображает кнопку Quasar (<q-btn>), которая показывает текст из props.label, имеет цвет props.color и эмитит событие при клике.
Теперь создадим историю для этого компонента.
Создайте файл истории: src/components/MyButton.stories.ts:
import MyButton from './MyButton.vue';
import type { Meta, StoryObj } from '@storybook/vue3';
// Описание компонента для Storybook
const meta: Meta<typeof MyButton> = {
title: 'Components/MyButton', // Заголовок/раздел в каталоге Storybook
component: MyButton,
tags: ['autodocs'], // Автодокументация (Storybook 7+)
argTypes: {
// Настройка контролов (опционально).
label: { control: 'text' }, // Prop 'label' будет представлен как текстовый контрол
color: { control: 'text' } // Prop 'color' также как текст (можно сделать select из вариантов)
}
};
export default meta;
// Тип для story-объектов (на основе Meta)
type Story = StoryObj<typeof meta>;
// Экспортируем вариации компонента как константы
export const Primary: Story = {
args: {
label: 'Основная кнопка',
color: 'primary'
}
};
export const Secondary: Story = {
args: {
label: 'Вторичная кнопка',
color: 'secondary'
}
};
Разберем эту историю:
- title: определяет, как будет называться компонент в интерфейсе Storybook. Здесь он появится в разделе Components как MyButton.
- component: ссылка на сам компонент, который рендерится.
- argTypes: мы указали, что для пропсов label и color нужно показывать контролы (тип 'text' означает текстовое поле ввода). Это позволит изменять пропсы прямо из интерфейса Storybook.
- Мы экспортировали два варианта истории: Primary и Secondary, задавая для них разные аргументы (args). Primary отрисует кнопку с синим цветом (primary), а Secondary – с серым (secondary), при прочих равных. Вы можете добавлять любые варианты, меняя args, чтобы показывать различные состояния компонента.
Storybook автоматически отрисует компонент MyButton с заданными пропсами. Благодаря тому, что мы зарегистрировали Quasar, <q-btn> внутри будет работать, а благодаря argTypes – в панели Controls Storybook появятся поля для интерактивного изменения label и color.
Проверка истории: Убедитесь, что Storybook запущен (npm run storybook). В панели Stories вы должны увидеть раздел Components и внутри него – MyButton с двумя вариантами: Primary и Secondary. Попробуйте переключаться между ними и менять значения контролов (например, текст метки или цвет кнопки) – компонент будет обновляться в реальном времени.
5. Запуск и использование Storybook
Чтобы запустить Storybook, используется команда (как правило, добавлена в package.json):
npm run storybook
Она поднимает dev-сервер Storybook. После запуска консоль покажет URL, по умолчанию это http://localhost:6006. Откройте его в браузере – перед вами интерфейс Storybook.
Как пользоваться Storybook:
- Слева находится список ваших историй (Components/MyButton и т.д., согласно title в экспортируемых мета-данных). Можно сгруппировать истории по категориям через разделители в названии (мы указали "Components/MyButton", поэтому Storybook создал группу Components).
- Справа отображается рендер компонента. Вы можете взаимодействовать с компонентом прямо там (кликать по кнопкам, вводить текст и т.д.).
Внизу или сбоку (в зависимости от версии UI) есть панели Controls, Actions, Docs:
- Controls позволяет интерактивно менять пропсы компонента, которые вы описали в argTypes (или Storybook определил сам). Для нашего примера там будут поля для label и color.
- Actions отображает события (действия), например, если компонент эмитит событие и оно описано как onSomething, Storybook мог бы логировать его. В нашем случае событие 'click' на кнопке можно увидеть, если нажать кнопку – Storybook отобразит действие click в разделе Actions (благодаря параметру actions: { argTypesRegex: '^on[A-Z].*' } по умолчанию).
- Docs (если включен addon docs/autodocs) – генерирует документацию по компоненту: список пропсов, примеры использования и т.д., на основе JSDoc и метаданных. Мы включили тег autodocs, поэтому в Storybook 7+ должен появиться раздел Docs для компонента, где автоматически документированы пропсы label и color.
При сохранении изменений в компонентах или историях Storybook автоматически перезагрузит предпросмотр (HMR – hot module replacement), поэтому вы мгновенно увидите обновления. Это очень удобный цикл разработки: можно править компонент и сразу видеть результат в Storybook.
Совет: Помимо режима разработки, Storybook позволяет собрать статическую версию (например, для документации). Команда npm run build-storybook создаст статический сайт (в папке storybook-static), который можно развернуть на хостинге и предоставить команде или заказчику как живую документацию компонентов.
6. Полезные советы и устранение частых ошибок
Настройка Storybook под Quasar может вызвать несколько распространенных проблем. Рассмотрим их и способы решения:
Alias (пути импорта) не распознаются: Если при запуске Storybook в консоли появляются ошибки вида “Cannot resolve module ...” на пути вроде 'src/components/...' или '@/assets/...', значит Storybook не знает о ваших алиасах. Решение – как мы делали выше: добавить соответствующие alias в конфиг .storybook/main.js (через viteFinal или webpackFinal). Например, добавить 'src' и '@' указывающие на папку src. После этого импорты будут работать.
Quasar-компоненты не отображаются (пустой рендер или ошибки Vue): Вероятно, вы забыли установить Quasar в preview.js. В Quasar-компонентах (например, <q-btn>) логика регистрации происходит через плагин Quasar. Если не вызвать app.use(Quasar), Storybook не знает, как отрендерить <q-btn>, и вы можете увидеть пустое место или ошибку в консоли. Решение – убедиться, что в .storybook/preview.js выполнено app.use(Quasar, {}) (с необходимыми плагинами). После добавления Quasar-плагина компоненты станут доступны.
Отсутствуют стили Quasar в Storybook: Компоненты появились, но выглядят "голыми" или некорректно стилизованными? Значит, не подключены CSS Quasar. Проверьте, что в preview.js импортирован основной CSS (quasar/dist/quasar.css). Также, если вы используете определенные иконки или шрифты, подключите соответствующие файлы из @quasar/extras. Например, для Material Icons и Roboto мы импортировали их CSS. Без этих файлов иконки могут не отображаться, а шрифт по умолчанию может отличаться. Добавьте недостающие импорты, и стили применятся.
Конфликт версий PostCSS/Autoprefixer: В некоторых случаях Storybook может конфликтовать с более новой версией Autoprefixer, используемой Quasar (или наоборот). Проявляется это как ошибка при сборке, связанная с PostCSS. Например, Storybook (особенно версии до 7) требовал PostCSS 7 и autoprefixer 9. Если Quasar-проект тянет autoprefixer 10+, может возникнуть ошибка. Решение, которое предлагалось сообществом – установить autoprefixer@9 как зависимость проекта, чтобы Storybook использовал совместимую версию. То есть:
npm install -D autoprefixer@^9
Однако, начиная с Storybook 7+ на Vite, эта проблема встречается реже, так как Vite использует PostCSS 8. Если вы столкнулись с подобной ошибкой, попробуйте указанный фикс. Более свежие версии Storybook могут уже решить этот конфликт.
Storybook не видит файлы TypeScript или Vue: Если истории не подхватываются или вы видите ошибки TS, убедитесь, что в .storybook/main.js правильно указан шаблон для stories, включающий нужные расширения: **/*.stories.@(js|jsx|ts|tsx|mdx). В нашем примере мы используем .stories.ts, это соответствует шаблону. Также проверьте tsconfig.json – возможно, нужно добавить "include": ["src/**/*.stories.ts"], чтобы TypeScript не пропускал файлы с историями при типизации. Впрочем, это не критично для сборки, но IDE может ругаться без include.
Использование Quasar-темы и переменных: Если вы кастомизируете тему Quasar через SCSS-переменные (например, файл quasar.variables.sass), то заметите, что Storybook по умолчанию их не применяет. Причина – Storybook не знает о ваших переменных, он просто подключил готовый CSS Quasar. Есть несколько подходов:
Импортировать SCSS переменные и стили в Storybook: Вы можете попытаться импортировать ваш файл переменных перед импортом стилей Quasar. Например, в preview.js:
import 'src/css/quasar.variables.sass';
import 'quasar/src/css/index.sass'; // импорт исходников Quasar, которые учитывают переменные
Однако при таком подходе нужно настроить обработку Sass в Storybook. В Vite-билдере Sass должен работать из коробки (если в проекте установлена sass), так как Quasar-приложение уже тянет ее. Убедитесь, что пакет sass установлен (Quasar CLI ставит его при выборе SCSS). Импортируя quasar/src/css/index.sass, вы заставите Vite пересобрать стили Quasar с учетом ваших кастомных переменных.
Альтернативный способ – использовать скомпилированный CSS: Можно поступить проще: собрать ваше Quasar-приложение обычным способом и взять из него готовый CSS со стилями темы. Например, один из разработчиков предлагает такой путь stackoverflow.com:
Выполнить quasar build для приложения, получить финальный CSS со всеми стилями (например, dist/spa/css/app.css).
Скопировать этот CSS в папку .storybook (назвав, например, quasar-styles.css).
Импортировать этот файл в preview.js вместо (или дополняя) стандартных стилей:
import './quasar-styles.css';
Таким образом, Storybook загрузит уже готовые стили вашего приложения, включая все кастомизации. Можно автоматизировать этот процесс скриптом (как в упомянутом совете, где в package.json для Storybook запускается скрипт сборки Quasar перед стартом Storybook stackoverflow.com). Недостаток этого способа – нужно повторять при изменении темы, но для редкой настройки это приемлемо.
Другие библиотеки (Pinia, Vue Router, i18n): Если ваш Quasar-проект использует, к примеру, Pinia для управления состоянием или Vue Router, и компоненты зависят от этого, их тоже стоит интегрировать в Storybook. Сделать это можно аналогично: в preview.js импортировать и установить нужные плагины. Например, для Pinia:
import { createPinia } from 'pinia';
app.use(createPinia());
для Vue Router потребуется создать инстанс роутера (возможно, с маршрутом-заглушкой) и подключить его:
import { router } from '../src/router'; // ваш роутер, или сконфигурируйте отдельно
app.use(router);
для i18n:
import { i18n } from '../src/i18n';
app.use(i18n);
Такие подключения должны выполняться до монтирования историй, в процессе инициализации (мы как раз используем для этого preview.js).
Благодаря этому ваши компоненты будут получать $store, $t и прочие вещи, как если бы работали в реальном приложении.
Настроив однажды Storybook под Quasar, вы получаете мощный инструмент для изолированной разработки компонентов. Вы можете создавать истории для каждого компонента, визуально тестировать разные состояния (пропсы, комбинации, взаимодействия) без необходимости запускать всё приложение. Это ускоряет разработку и упрощает командную работу – дизайнеры и тестировщики могут просмотреть компонентную библиотеку в Storybook.
Теперь начинающие разработчики Quasar имеют пошаговый план, как развернуть Storybook в своем проекте. Удачной разработки и чистых историй!
Ссылки на источники и дополнительную информацию: