加入在线会议:周四,美国东部时间上午 11 点,Storybook 9 发布及 AMA
文档
Storybook 文档

Storybook for SvelteKit

Storybook for SvelteKit 是一个框架,它使为 SvelteKit 应用独立开发和测试 UI 组件变得容易。它包括

  • 🪄 零配置
  • 🧩 轻松模拟许多 SvelteKit 模块
  • 🔗 自动链接处理
  • 💫 还有更多!

要求

  • SvelteKit ≥ 1.0

入门

在没有 Storybook 的项目中

在 SvelteKit 项目的根目录运行此命令后,按照提示操作

npm create storybook@latest

更多关于 Storybook 入门的信息。

在已有 Storybook 的项目中

此框架设计用于 Storybook 7+。如果您尚未使用 v7,请使用此命令进行升级

npx storybook@next upgrade

自动迁移

运行上述 upgrade 命令时,您应该会收到提示,要求迁移到 @storybook/sveltekit,它会为您处理一切。如果自动迁移适用于您的项目,请参考下面的手动迁移。

手动迁移

首先,安装框架

npm install --save-dev @storybook/sveltekit

然后,更新您的 .storybook/main.js|ts 文件以更改 framework 属性

.storybook/main.ts
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 中定义它

MyComponent.stories.js|ts
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 字符串,值定义您的模拟。例如

MyComponent.stories.js|ts
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

CLI 的 add 命令会自动安装和设置插件。要手动安装,请参阅我们的文档,了解如何安装插件。

更新您的 Storybook 配置文件(即 .storybook/main.js|ts)以启用对此格式的支持。

.storybook/main.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)并提供额外的插件选项。下面列出了可用选项及其使用示例。

.storybook/main.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 组件。

MyComponent.stories.svelte
<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 结构。

MyComponent.stories.svelte
<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 代码片段,让您在不损失响应性的情况下创建动态故事。

MyComponent.stories.svelte
<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。此属性允许您根据特定条件对故事进行分类和过滤,并根据应用于故事的标签生成文档。

MyComponent.stories.svelte
<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,则会将操作记录到操作面板。请参阅模拟链接获取示例。

类型: 请参阅SvelteKit 文档

$app/navigation 模块提供模拟。

类型: 请参阅SvelteKit 文档

每当调用 goto 时将调用的回调函数。如果未提供函数,则会将操作记录到操作面板

类型: 请参阅SvelteKit 文档

每当调用 pushState 时将调用的回调函数。如果未提供函数,则会将操作记录到操作面板

类型: 请参阅SvelteKit 文档

每当调用 replaceState 时将调用的回调函数。如果未提供函数,则会将操作记录到操作面板

类型: 请参阅SvelteKit 文档

每当调用 invalidate 时将调用的回调函数。如果未提供函数,则会将操作记录到操作面板

类型: 请参阅SvelteKit 文档

每当调用 invalidateAll 时将调用的回调函数。如果未提供函数,则会将操作记录到操作面板

类型: 请参阅SvelteKit 文档

一个对象,将传递给 afterNavigate 函数,该函数将在 onMount 事件触发时被调用。

stores

类型: 请参阅SvelteKit 文档

$app/stores 模块提供模拟。

stores.navigating

类型: 请参阅SvelteKit 文档

navigating store 的部分版本。

stores.page

类型: 请参阅SvelteKit 文档

page store 的部分版本。

stores.updated

类型: boolean

一个布尔值,代表 updated 的值(您也可以访问 updated.check(),它将是一个无操作)。

选项

您可以传递一个 options 对象以进行额外的配置(如果需要)

.storybook/main.ts
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 一起使用时不再支持(也不再需要)该属性。