Storybook for SvelteKit
Storybook for SvelteKit 是一个框架,它使为 SvelteKit 应用独立开发和测试 UI 组件变得容易。它包括
- 🪄 零配置
- 🧩 轻松模拟许多 SvelteKit 模块
- 🔗 自动链接处理
- 💫 还有更多!
要求
- SvelteKit ≥ 1.0
入门
在没有 Storybook 的项目中
在 SvelteKit 项目的根目录运行此命令后,按照提示操作
npm create storybook@latest
在已有 Storybook 的项目中
此框架设计用于 Storybook 7+。如果您尚未使用 v7,请使用此命令进行升级
npx storybook@next upgrade
自动迁移
运行上述 upgrade
命令时,您应该会收到提示,要求迁移到 @storybook/sveltekit
,它会为您处理一切。如果自动迁移适用于您的项目,请参考下面的手动迁移。
手动迁移
首先,安装框架
npm install --save-dev @storybook/sveltekit
然后,更新您的 .storybook/main.js|ts
文件以更改 framework 属性
import type { StorybookConfig } from '@storybook/sveltekit';
const config: StorybookConfig = {
// ...
framework: '@storybook/sveltekit', // 👈 Add this
// svelteOptions: { ... }, 👈 Remove this
};
export default config;
最后,这些包现在要么已废弃,要么已成为 @storybook/sveltekit
的一部分,因此您不再需要直接依赖它们。您可以从项目中移除它们(npm uninstall
, yarn remove
, pnpm remove
)
@storybook/svelte-vite
storybook-builder-vite
@storybook/builder-vite
支持的功能
所有 Svelte 语言特性都开箱即用,因为 Storybook 框架直接使用 Svelte 编译器。然而,SvelteKit 有一些不受支持的特定 Kit 模块。以下是在 Storybook 中哪些模块可用,哪些不可用的明细:
模块 | 状态 | 注意 |
---|---|---|
$app/environment | ✅ 支持 | 在 Storybook 中,version 始终为空。 |
$app/forms | ⚠️ 实验性 | 请参阅如何模拟。 |
$app/navigation | ⚠️ 实验性 | 请参阅如何模拟。 |
$app/paths | ✅ 支持 | 需要 SvelteKit 1.4.0 或更高版本。 |
$app/stores | ⚠️ 实验性 | 请参阅如何模拟。 |
$env/dynamic/public | 🚧 部分支持 | 仅在开发模式下支持。Storybook 是作为静态应用构建的,没有服务端 API,因此无法动态提供内容。 |
$env/static/public | ✅ 支持 | |
$lib | ✅ 支持 | |
@sveltejs/kit/* | ✅ 支持 | |
$env/dynamic/private | ⛔ 不支持 | 这是服务端特性,而 Storybook 在客户端渲染所有组件。 |
$env/static/private | ⛔ 不支持 | 这是服务端特性,而 Storybook 在客户端渲染所有组件。 |
$service-worker | ⛔ 不支持 | 这是 Service Worker 特性,不适用于 Storybook。 |
如何模拟
要模拟 SvelteKit 导入,可以在 parameters.sveltekit_experimental
中定义它
export const MyStory = {
parameters: {
sveltekit_experimental: {
stores: {
page: {
data: {
test: 'passed',
},
},
navigating: {
route: {
id: '/storybook',
},
},
updated: true,
},
},
},
};
可用参数在下方的 API 部分有文档说明。
模拟链接
默认的链接处理行为(例如,点击 <a href="..." />
元素时)是将操作记录到操作面板。
您可以通过将一个对象赋值给 parameters.sveltekit_experimental.hrefs
来覆盖此行为,其中键表示 href 字符串,值定义您的模拟。例如
export const MyStory = {
parameters: {
sveltekit_experimental: {
hrefs: {
'/basic-href': (to, event) => {
console.log(to, event);
},
'/root.*': {
callback: (to, event) => {
console.log(to, event);
},
asRegex: true,
},
},
},
},
};
有关更多信息,请参阅API 参考。
编写原生 Svelte 故事
Storybook 提供了一个由社区维护的 Svelte 插件,使您能够使用模板语法为 Svelte 组件编写故事。
社区积极维护 Svelte CSF 插件,但它仍然缺少 Storybook 官方 Svelte 框架支持中当前可用的一些功能。有关更多信息,请参阅该插件的文档。
设置
如果您使用 SvelteKit 框架初始化了项目,该插件已经为您安装和配置好了。但是,如果您正在从以前的版本迁移,则需要采取额外步骤来启用此功能。
运行以下命令安装插件。
npx storybook@latest add @storybook/addon-svelte-csf
更新您的 Storybook 配置文件(即 .storybook/main.js|ts
)以启用对此格式的支持。
// Replace your-framework with svelte-vite or sveltekit
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx|svelte)'],
addons: [
// Other Storybook addons
'@storybook/addon-svelte-csf',
],
};
export default config;
配置
默认情况下,Svelte 插件为 Storybook 的 SvelteKit 框架提供了零配置支持。但是,您可以扩展 Storybook 配置文件(即 .storybook/main.js|ts
)并提供额外的插件选项。下面列出了可用选项及其使用示例。
// Replace your-framework with the name of your Svelte framework
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
// Other configuration
addons: [
{
name: '@storybook/addon-svelte-csf',
options: {
legacyTemplate: true, // Enables the legacy template syntax
},
},
],
};
export default config;
选项 | 描述 |
---|---|
legacyTemplate | 启用对 Template 组件的支持以实现向后兼容。options: { legacyTemplate: true } |
启用 legacyTemplate
选项可能会引入性能开销,应谨慎使用。有关更多信息,请参阅该插件的文档。
升级到 Svelte CSF 插件 v5
随着 Svelte 5 的发布,Storybook 的 Svelte CSF 插件已更新以支持新功能。本指南将帮助您迁移到最新版本的插件。下面是 5.0 版本的主要更改概述以及升级项目所需的步骤。
简化的故事 API
如果您使用 Meta
组件或 meta
命名导出定义故事的元数据(例如,参数),则需要更新故事以使用新的 defineMeta
函数。此函数返回一个包含所需信息的对象,其中包括一个您必须用来定义组件故事的 Story
组件。
<script>
import { Meta, Story } from '@storybook/addon-svelte-csf';
import MyComponent from './MyComponent.svelte';
</script>
<Meta title="MyComponent" component={MyComponent} />
<Story name="Default" />
故事模板
如果您使用 Template
组件来控制组件在 Storybook 中的渲染方式,此功能已被 Story
组件内置的子组件支持所取代,使您能够直接在故事中组合组件和定义 UI 结构。
<script>
import { Meta, Template, Story } from '@storybook/addon-svelte-csf';
import OuterComponent from './OuterComponent.svelte';
import MyComponent from './MyComponent.svelte';
</script>
<Meta title="MyComponent" component={MyComponent} />
<Template let:args>
<OuterComponent>
<MyComponent />
</OuterComponent>
</Template>
<Story name="Default" />
如果您需要支持 Template
组件,该插件提供了一个特性标志以实现向后兼容。有关更多信息,请参阅配置选项。
故事槽点 (slots) 转代码片段 (snippets)
随着 Svelte 槽点(slot)的弃用和可复用代码片段(snippets)
的引入,该插件也引入了对此功能的支持,允许您扩展 Story
组件并提供自定义代码片段来为您的故事提供动态内容。Story
接受一个 template
代码片段,让您在不损失响应性的情况下创建动态故事。
<script>
import { defineMeta } from '@storybook/addon-svelte-csf';
import MyComponent from './MyComponent.svelte';
const { Story } = defineMeta({
component: MyComponent,
});
</script>
<Story name="Default" args={{ exampleProperty: true }}>
{#snippet template(args)}
<MyComponent {...args}>Reactive component</MyComponent>
{/snippet}
</Story>
标签支持
如果您使用 autodocs
故事属性启用了自动文档生成,则必须将其替换为tags
。此属性允许您根据特定条件对故事进行分类和过滤,并根据应用于故事的标签生成文档。
<script>
import { Meta, Template, Story } from '@storybook/addon-svelte-csf';
import MyComponent from './MyComponent.svelte';
</script>
<Meta title="MyComponent" component={MyComponent} />
<Template let:args>
<MyComponent {...args} />
</Template>
<Story name="Default" autodocs />
API
参数
此框架在 sveltekit_experimental
命名空间下为 Storybook 贡献了以下参数
forms
类型: { enhance: () => void }
为 $app/forms
模块提供模拟。
forms.enhance
类型: () => void
当带有 use:enhance
的表单提交时将调用的回调函数。
hrefs
类型: Record<[path: string], (to: string, event: MouseEvent) => void | { callback: (to: string, event: MouseEvent) => void, asRegex?: boolean }>
如果在您的代码中有一个 <a />
标签,其 href
属性与定义的一个或多个链接匹配(如果 asRegex
属性为 true
,则按正则表达式处理),则将调用相应的 callback
函数。如果未定义匹配的 hrefs
,则会将操作记录到操作面板。请参阅模拟链接获取示例。
navigation
类型: 请参阅SvelteKit 文档
为 $app/navigation
模块提供模拟。
navigation.goto
类型: 请参阅SvelteKit 文档
每当调用 goto
时将调用的回调函数。如果未提供函数,则会将操作记录到操作面板。
navigation.pushState
类型: 请参阅SvelteKit 文档
每当调用 pushState
时将调用的回调函数。如果未提供函数,则会将操作记录到操作面板。
navigation.replaceState
类型: 请参阅SvelteKit 文档
每当调用 replaceState
时将调用的回调函数。如果未提供函数,则会将操作记录到操作面板。
navigation.invalidate
类型: 请参阅SvelteKit 文档
每当调用 invalidate
时将调用的回调函数。如果未提供函数,则会将操作记录到操作面板。
navigation.invalidateAll
类型: 请参阅SvelteKit 文档
每当调用 invalidateAll
时将调用的回调函数。如果未提供函数,则会将操作记录到操作面板。
navigation.afterNavigate
类型: 请参阅SvelteKit 文档
一个对象,将传递给 afterNavigate
函数,该函数将在 onMount
事件触发时被调用。
stores
类型: 请参阅SvelteKit 文档
为 $app/stores
模块提供模拟。
stores.navigating
类型: 请参阅SvelteKit 文档
navigating
store 的部分版本。
stores.page
类型: 请参阅SvelteKit 文档
page
store 的部分版本。
stores.updated
类型: boolean
一个布尔值,代表 updated
的值(您也可以访问 updated.check()
,它将是一个无操作)。
选项
您可以传递一个 options 对象以进行额外的配置(如果需要)
import type { StorybookConfig } from '@storybook/sveltekit';
const config: StorybookConfig = {
// ...
framework: {
name: '@storybook/sveltekit',
options: {
// ...
},
},
};
export default config;
可用选项如下
builder
类型: Record<string, any>
配置框架构建器的选项。对于 SvelteKit,可用选项可在Vite 构建器文档中找到。
故障排除
启动 Storybook 时出错
在升级到 v7.0 后启动 Storybook 时,可能会出现以下错误并退出
ERR! SyntaxError: Identifier '__esbuild_register_import_meta_url__' has already been declared
这可能在从 6.5 手动升级到 7.0 时发生。要解决此问题,您需要删除 .storybook/main.js
中的 svelteOptions
属性,因为 Storybook 7+ 与 SvelteKit 一起使用时不再支持(也不再需要)该属性。