Storybook 集成
什么是 Storybook
Storybook 是一个开源工具,用于独立构建、测试和文档化 UI 组件。它为开发者提供了一个独立于主应用程序的环境,使组件开发更加高效和有条理。
主要特点
- 隔离环境:在应用程序上下文之外开发 UI 组件
- 组件驱动开发:专注于一次构建一个组件
- 可视化测试:直观地检查组件在不同状态下的外观
- 交互式文档:创建活跃的、可交互的组件文档
- 插件生态系统:通过众多插件扩展功能
使用场景
- 创建设计系统或组件库
- 开发复杂的 UI 界面
- 测试组件的边缘情况
- 协作开发(设计师和开发者)
项目集成
Storybook 的 cli 貌似不太好用,这边提供一个将 Storybook 与 Vite 项目集成的方案。
环境要求
- bun
- React ≥ 16.8
- Vite ≥ 4.0
- Storybook ≥ 8.0
创建项目
$ bun create vite
reused 0, downloaded 1, added 1, done
|
o Project name:
| storybook-demo
|
o Select a framework:
| React
|
o Select a variant:
| TypeScript + SWC
|
o Scaffolding project in D:\Projects\storybook-demo...
|
— Done. Now run:
cd storybook-demo
bun install
bun run dev
$ bun install
...项目结构:
$ tree
.
|-- README.md
|-- eslint.config.js
|-- index.html
|-- package.json
|-- public
| `-- vite.svg
|-- src
| |-- App.css
| |-- App.tsx
| |-- assets
| | `-- react.svg
| |-- index.css
| |-- main.tsx
| `-- vite-env.d.ts
|-- tsconfig.app.json
|-- tsconfig.json
|-- tsconfig.node.json
`-- vite.config.ts
3 directories, 15 filesvite create 默认没有创建库项目的选项,下面我们将这个项目改造成库项目。
先删掉 src/ 下的 css、ts 和资源文件,创建一个空的 index.ts 文件,现在项目结构长这样:
$ tree
.
|-- README.md
|-- eslint.config.js
|-- index.html
|-- package.json
|-- src
| |-- index.ts
| `-- vite-env.d.ts
|-- tsconfig.app.json
|-- tsconfig.json
|-- tsconfig.node.json
`-- vite.config.ts
2 directories, 11 files修改 vite.config.ts 文件,将项目类型改为库项目:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
// 新增以下配置
build: {
lib: {
entry: 'src/index.ts',
name: 'my-components',
formats: ['es'],
}
}
})记得安装一下 sass 依赖,我们接下来要使用 scss 编写样式:
$ bun add -D sass-embedded
Packages: +20
++++++++++++++++++++
Progress: resolved 483, reused 403, downloaded 7, added 20, done
devDependencies:
+ sass-embedded 1.86.3
Done in 7.2s现在就是一个 React 库项目咯,可以开始集成 Storybook 了。
集成 Storybook
安装 Storybook:
// 安装 Storybook 时会调用 npm 安装一些包,如果 npm 环境有问题可以加上 --package-manager=bun
$ bun create storybook@latest
╭───────────────────────────────────────────────────────╮
│ │
│ Adding Storybook version 8.6.12 to your project.. │
│ │
╰───────────────────────────────────────────────────────╯
√ What do you want to use Storybook for? » Documentation: MDX, auto-generated component docs, Testing: Fast browser-based component tests, watch mode
• Detecting project type. ✓
Installing dependencies...
Lockfile is up to date, resolution step is skipped
Already up to date
Done in 678ms
• Adding Storybook support to your "React" app • Detected Vite project. Setting builder to Vite. ✓
✅ Getting the correct version of 0 packages
. ✓
Installing dependencies...
Lockfile is up to date, resolution step is skipped
Already up to date
Done in 750ms
> npx [email protected] add @storybook/[email protected]
Verifying @storybook/experimental-addon-test
Installing @storybook/experimental-addon-test@^8.6.12
Adding '@storybook/[email protected]' to the "addons" field in .storybook\main.ts
Running postinstall script for @storybook/experimental-addon-test
╭ 👋 Howdy! ─────────────────────────────────────────────────────────────────╮
│ │
│ I\'m the installation helper for @storybook/experimental-addon-test │
│ │
│ Hold on for a moment while I look at your project and get it set up... │
│ │
╰────────────────────────────────────────────────────────────────────────────╯
› Configuring Playwright with Chromium (this might take some time):
npx playwright install chromium --with-deps
╭ 🚨 Oh no! ──────────────────────────────────────────────────────────────╮
│ │
│ Found an existing Vitest setup file: │
│ D:/Projects/storybook-demo/.storybook/vitest.setup.ts │
│ │
│ Please refer to the documentation to complete the setup manually: │
│ https://storybook.js.org/docs/writing-tests/test-addon#manual-setup │
│ │
╰─────────────────────────────────────────────────────────────────────────╯
╭──────────────────────────────────────────────────────────────────────────────╮
│ │
│ Storybook was successfully installed in your project! 🎉 │
│ Additional features: Documentation, Testing │
│ │
│ To run Storybook manually, run bun run storybook. CTRL+C to stop. │
│ │
│ Wanna know more about Storybook? Check out https://storybook.js.org/ │
│ Having trouble or want to chat? Join us at https://discord.gg/storybook/ │
│ │
╰──────────────────────────────────────────────────────────────────────────────╯
Running Storybook
> [email protected] storybook D:\Projects\storybook-demo
> storybook dev -p 6006 "--initial-path=/onboarding" "--quiet"
@storybook/core v8.6.12
info => Serving static files from D:\Projects\storybook-demo\node_modules\.cache\storybook\default\coverage at /coverage
info Using tsconfig paths for react-docgen
17:58:40 [vite] (client) hmr update /@id/__x00__virtual:/@storybook/builder-vite/vite-app.js这里会自动打开 Storybook 的欢迎页面,按照指引操作即可。(注意让你命名新 stories 时不要和已有的 stories 重名)
完成上述操作以后的项目结构如下:
$ tree -F -I "node_modules"
.
|-- README.md
|-- eslint.config.js
|-- index.html
|-- package.json
|-- bun-lock.yaml
|-- src/
| |-- index.ts
| |-- stories/
| | |-- Button.stories.ts
| | |-- Button.tsx
| | |-- Configure.mdx
| | |-- Header.stories.ts
| | |-- Header.tsx
| | |-- Page.stories.ts
| | |-- Page.tsx
| | |-- assets/
| | | |-- accessibility.png
| | | |-- accessibility.svg
| | | |-- addon-library.png
| | | |-- assets.png
| | | |-- avif-test-image.avif
| | | |-- context.png
| | | |-- discord.svg
| | | |-- docs.png
| | | |-- figma-plugin.png
| | | |-- github.svg
| | | |-- share.png
| | | |-- styling.png
| | | |-- testing.png
| | | |-- theming.png
| | | |-- tutorials.svg
| | | `-- youtube.svg
| | |-- button.css
| | |-- header.css
| | `-- page.css
| `-- vite-env.d.ts
|-- tsconfig.app.json
|-- tsconfig.json
|-- tsconfig.node.json
|-- vite.config.ts
`-- vitest.workspace.ts
3 directories, 38 files我们先暂时忽略一下 src/stories/ 目录,在 src/components 中创建 Button 文件夹并添加如下几个文件:
$ tree ./src/components/Button/
./src/components/Button/
|-- Button.scss
|-- Button.stories.ts
|-- Button.test.ts
|-- Button.tsx
`-- index.ts
0 directories, 5 filesButton.tsx 文件可以直接复制 stories/Button.tsx 的内容,只要将首行的 import 语句导入的样式文件后缀名改成 scss 即可,Button.stories.ts 文件可以直接复制 stories/Button.stories.ts 的内容,Button.scss 文件也可以直接复制 stories/Button.css 的内容,因为 scss 是 css 的超集,可以无缝转换 ,Button.test.ts 文件暂时先不管,这里是组件测试的代码,笔者还没研究。
现在在 src\Button\index.ts 中导出组件:
import { Button } from './Button';
export default Button;
export type { ButtonProps } from './Button';在 src/index.ts 中导出组件:
export { default as Button } from './components/Button';现在可以把 src/stories 目录删掉啦,需要抄的代码已经抄完了,可以不用它了。删掉之前可以先看一看 src\stories\Configure.mdx 的内容,学习一下怎么使用 MDX 书写组件库文档。
完成后的项目结构:
$ tree -F -I "node_modules"
.
|-- README.md
|-- eslint.config.js
|-- index.html
|-- package.json
|-- bun-lock.yaml
|-- src/
| |-- components/
| | `-- Button/
| | |-- Button.scss
| | |-- Button.stories.ts
| | |-- Button.test.ts
| | |-- Button.tsx
| | `-- index.ts
| |-- index.ts
| `-- vite-env.d.ts
|-- tsconfig.app.json
|-- tsconfig.json
|-- tsconfig.node.json
|-- vite.config.ts
`-- vitest.workspace.ts
3 directories, 17 files现在就已经可以愉快的书写组件库啦😋,接下来我们来看看 Storybook 的使用。
Storybook 使用
在重构项目结构以后,打开 package.json,可以看到现在的脚本如下:
{
...,
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
...
}由于现在的项目是一个库项目,无法直接使用 vite 命令运行,所以我们可以稍作修改:
{
...,
"scripts": {
"dev": "storybook dev -p 6006",
"lint": "eslint .",
"build": "bun run build:js && bun run build:types && bun run build:css",
"build:js": "vite build",
"build:types": "tsc --emitDeclarationOnly",
"build:storybook": "storybook build"
},
...
}现在运行 bun dev 就可以直接启动 Storybook 开发服务器啦,快去试试吧🎉