Storybook 是一个用于独立构建 UI 组件和页面的前端开源工具,无需繁琐的工作即可构建 UI。前段时间刚刚发布了7.x版本,文本将简单介绍下其在webpack5和vite中的使用步骤。
关于什么是storybook,可以看官方介绍:storybook.js.org/docs/react/…
安装
需要有已经install过的项目,比如准备一个基于webpack5/vite4.x的react-ts项目
npx storybook@latest init
-
初始化安装过程很简单,因为cli会自动探测您的项目类型,如下图:
-
install后会自动通过
"storybook": "storybook dev -p 6006"
启动storybook dev
,截图如下:
`7.x版本还为用户添加了智能引导弹框,可以点击蓝色按钮即可观看版块功能介绍。
我们可以根据智能向导,在
src/stories/button.stories.tsx
文件末尾添加warning
类型的按钮export const Warning: Story = { args: { primary: true, label: 'Delete now', backgroundColor: 'red', } };
添加成功会有彩蛋
其他功能介绍
-
npm run storybook
之后可以点击configure-your-project--docs
查看, 每个功能都有查看详情,如下:
配置修改
比如添加alias配置
webpack5
需要扩展webpackFinal,当然也可以追加其他webpack配置
import type { StorybookConfig } from '@storybook/react-webpack5';
const config: StorybookConfig = {
// ...
webpackFinal: async (config) => {
if (config.resolve && config.resolve.alias) {
config.resolve.alias['@'] = resolve('../src');
config.resolve.alias['@assets'] = resolve('../src/assets');
// ...
}
return config;
},
};
export default config;
webpack5 ant-mobile集成
- 我们可以修改
.storybook/main.ts
import type { StorybookConfig } from '@storybook/react-webpack5';
const config: StorybookConfig = {
// ...
babel: async (options) => {
return {
...options,
plugins: [ // 动态导入antd-mobile
[
require.resolve('babel-plugin-import'),
{
libraryName: 'antd-mobile',
libraryDirectory: 'es/components',
style: false,
},
],
],
};
},
};
export default config;
webpack5 less/sass支持
vite不用单独配置,直接安装less/sass包即可
- 安装 @storybook/addon-styling
npm i @storybook/addon-styling -D
import type { StorybookConfig } from '@storybook/react-webpack5';
const config: StorybookConfig = {
// ...
addons: [
// ...
{
name: '@storybook/addon-styling',
options: {
// less 支持
less: {
implementation: require('less'),
},
// sass/scss 支持
sass: {
implementation: require('sass'),
},
// postcss 支持
postCss: {
implementation: require("postcss"),
},
},
},
],
// ...
};
export default config;
vite
-
vite-storybook
相对webpack5-storybook
来说比较智能,会自动继承vite.config.ts
中的配置 (注意storybook v6需要通过viteFinal进行额外配置) -
如果项目中安装过
less
sass
包,那么storybook
会自动支持,开箱即用 (注意:wepbpack依然需要单独配置,详见wepack5-less/sass支持)
并且你依然可以继续扩展viteFinal
import type { StorybookConfig } from '@storybook/react-vite';
import { mergeConfig } from 'vite';
import path from 'path';
const config: StorybookConfig = {
// ...
async viteFinal(config, { configType }) {
// const isBuild = configType !== 'DEVELOPMENT';
return mergeConfig(config, {
resolve: {
alias: [
...(
Object.entries({
'classnames': 'classnames-es-ts',
'@': path.resolve('src'),
'@components': path.resolve('src/components'),
// ...
}).map(([key, val]) => ({ find: key, replacement: val }))
),
],
},
// ...
});
},
};
export default config;
vite ant-mobile集成
直接在vite.config.ts
中添加即可
关于px to rem后页面显示问题
如果您的项目使用了postcss-plugin-px2rem
插件, storybook预览后,元素或字体显示会变小,如下图所示:
这是因为所有的px被转成了rem,而文档默认base是16px,所以会自动缩小
处理方法:
-
创建
.storybook/preview-body.html
以下的转换只是案例 (我的例子是适配移动端),具体可以根据需求进行调整
<script> (function (doc, win) { var docEl = doc.documentElement, resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize', recalc = function () { const base = 100; var clientWidth = docEl.clientWidth; if (!clientWidth) return; if (clientWidth >= 750) { docEl.style.fontSize = `${base}px`; } else { docEl.style.fontSize = base * (clientWidth / 750) + 'px'; } }; if (!doc.addEventListener) return; win.addEventListener(resizeEvt, recalc, false); doc.addEventListener('DOMContentLoaded', recalc, false); })(document, window); </script>
-
刷新页面即可
预览机型添加
我的场景是适配移动端,比如我们添加一些常用机型,如iphone5
修改.storybook/preview.ts
即可
import type { Preview } from '@storybook/react';
import { MINIMAL_VIEWPORTS } from '@storybook/addon-viewport';
const customViewports = {
pixel2: {
name: 'Pixel 2',
styles: {
width: '411px',
height: '731px',
},
},
iphone5: {
name: 'iPhone 5/SE',
styles: {
width: '320px',
height: '568px',
},
},
iphone678: {
name: 'iPhone 6/7/8',
styles: {
width: '375px',
height: '667px',
},
},
};
const preview: Preview = {
parameters: {
padded: false,
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
viewport: {
viewports: {
...MINIMAL_VIEWPORTS,
...customViewports,
},
},
},
};
export default preview;