Docs
Storybook Docs

图片、字体和资源

组件通常依赖图片、视频、字体和其他资源来按照用户的期望进行渲染。在你的故事文件中,有很多方法可以使用这些资源。

¥Components often rely on images, videos, fonts, and other assets to render as the user expects. There are many ways to use these assets in your story files.

将资源导入故事

¥Import assets into stories

你可以通过导入(或要求)它们来导入任何媒体资源。它在我们的默认配置下开箱即用。但是,如果你使用自定义 webpack 配置,则需要添加 文件加载器 来处理所需的文件。

¥You can import any media assets by importing (or requiring) them. It works out of the box with our default config. But, if you are using a custom webpack config, you’ll need to add the file loader to handle the required files.

之后,你可以在故事中使用任何资源:

¥Afterward, you can use any asset in your stories:

MyComponent.stories.ts|tsx
import type { Meta, StoryObj } from '@storybook/react';
 
import imageFile from './static/image.png';
 
import { MyComponent } from './MyComponent';
 
const meta: Meta<typeof MyComponent> = {
  component: MyComponent,
};
 
export default meta;
type Story = StoryObj<typeof MyComponent>;
 
const image = {
  src: imageFile,
  alt: 'my image',
};
 
export const WithAnImage: Story = {
  render: () => <img src={image.src} alt={image.alt} />,
};

通过 Storybook 配置提供静态文件

¥Serving static files via Storybook Configuration

我们建议通过 Storybook 提供静态文件,以确保你的组件始终拥有需要加载的资源。我们建议将此技术用于你的组件经常使用的资源,如徽标、字体和图标。

¥We recommend serving static files via Storybook to ensure that your components always have the assets they need to load. We recommend this technique for assets that your components often use, like logos, fonts, and icons.

在启动 Storybook 时配置你的资源所在的目录(或目录列表)。使用主 Storybook 配置文件(即 .storybook/main.js|ts)中的 staticDirs 配置元素来指定目录:

¥Configure a directory (or a list of directories) where your assets live when starting Storybook. Use the staticDirs configuration element in your main Storybook configuration file (i.e., .storybook/main.js|ts) to specify the directories:

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  staticDirs: ['../public', '../static'],
};
 
export default config;

这里 ../public 是你的静态目录。现在在这样的组件或故事中使用它。

¥Here ../public is your static directory. Now use it in a component or story like this.

MyComponent.stories.ts|tsx
import type { Meta, StoryObj } from '@storybook/react';
 
import { MyComponent } from './MyComponent';
 
const meta: Meta<typeof MyComponent> = {
  component: MyComponent,
};
 
export default meta;
type Story = StoryObj<typeof MyComponent>;
 
// Assume image.png is located in the "public" directory.
export const WithAnImage: Story = {
  render: () => <img src="/image.png" alt="my image" />,
};

你还可以传递用逗号分隔的目录列表(不带空格),而不是单个目录。

¥You can also pass a list of directories separated by commas without spaces instead of a single directory.

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  staticDirs: ['../public', '../static'],
};
 
export default config;

或者甚至使用配置对象来定义目录:

¥Or even use a configuration object to define the directories:

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  staticDirs: [{ from: '../my-custom-assets/images', to: '/assets' }],
};
 
export default config;

从 CDN 引用资源

¥Reference assets from a CDN

将文件上传到在线 CDN 并引用它们。在此示例中,我们使用占位符图片服务。

¥Upload your files to an online CDN and reference them. In this example, we’re using a placeholder image service.

MyComponent.stories.ts|tsx
import type { Meta, StoryObj } from '@storybook/react';
 
import { MyComponent } from './MyComponent';
 
const meta: Meta<typeof MyComponent> = {
  component: MyComponent,
};
 
export default meta;
type Story = StoryObj<typeof MyComponent>;
 
export const WithAnImage: Story = {
  render: () => (
    <img src="https://storybook.js.org/images/placeholders/350x150.png" alt="My CDN placeholder" />
  ),
};

绝对路径与相对路径

¥Absolute versus relative paths

有时,你可能希望将 Storybook 部署到子路径中,例如 https://example.com/storybook

¥Sometimes, you may want to deploy your Storybook into a subpath, like https://example.com/storybook.

在这种情况下,你需要让所有图片和媒体文件都具有相对路径。否则,浏览器无法找到这些文件。

¥In this case, you need to have all your images and media files with relative paths. Otherwise, the browser cannot locate those files.

如果你通过导入加载静态内容,这是自动的,你无需执行任何操作。

¥If you load static content via importing, this is automatic, and you do not have to do anything.

假设你正在 静态目录 中与 Storybook 一起提供资源。在这种情况下,你需要使用相对路径来加载图片或使用基本元素。

¥Suppose you are serving assets in a static directory along with your Storybook. In that case, you need to use relative paths to load images or use the base element.

在故事中引用字体

¥Referencing Fonts in Stories

配置 Storybook 以从静态文件夹提供资源后,你可以在 Storybook 中引用这些资源。例如,你可以引用自定义字体并将其应用于你的故事。为此,请在配置目录(即 .storybook)内创建一个 preview-head.html 文件,并添加一个 <link /> 标签来引用你的字体。

¥After configuring Storybook to serve assets from your static folder, you can reference those assets in Storybook. For example, you can reference and apply a custom font to your stories. To do this, create a preview-head.html file inside the configuration directory (i.e., .storybook) and add a <link /> tag to reference your font.

{/* .storybook/preview-head.html */}
 
{/* Pull in static files served from your Static directory or the internet */}
{/* Example: `main.js|ts` is configured with staticDirs: ['../public'] and your font is located in the `fonts` directory inside your `public` directory */}
<link rel="preload" href="/fonts/my-font.woff2" />
 
{/* Or you can load custom head-tag JavaScript: */}
 
<script src="https://use.typekit.net/xxxyyy.js"></script>
<script>
  try {
    Typekit.load();
  } catch (e) {}
</script>