内容简介:Storybook是一个辅助UI控件开发的工具。通过story创建独立的控件,让每个控件开发都有一个独立的开发调试环境。 Storybook的运行不依赖于项目,开发人员不用担心由于开发环境、依赖问题导致不能开发控件。Storybook支持的框架覆盖主流的框架(React、Vue、Angular)。 由于使用React作为技术栈,本文将介绍使用react的项目如何配置Storybook环境。至此,根据
什么是Storybook
Storybook是一个辅助UI控件开发的工具。通过story创建独立的控件,让每个控件开发都有一个独立的开发调试环境。 Storybook的运行不依赖于项目,开发人员不用担心由于开发环境、依赖问题导致不能开发控件。
Storybook支持的框架覆盖主流的框架(React、Vue、Angular)。 由于使用React作为技术栈,本文将介绍使用react的项目如何配置Storybook环境。
安装
- 全局安装Storybook
npm i -g storybook 复制代码
- 执行以下命令安装@storybook/react
npm i --save-dev @storybook/react 复制代码
- 在package.json文件中
{ "scripts": { "storybook": "start-storybook -p 9001 -c .storybook" } } 复制代码
-
在工程根目录创建
.storybook
目录 -
在
.storybook
目录下创建config.js
文件
import { configure } from '@storybook/react'; import 'index.scss'; function loadStories() { require('./stories/userStory'); } configure(loadStories, module); 复制代码
-
创建story
虽然官方推荐在项目根目录下创建
stories
目录,但我比较喜欢在.storybook
目录下创建一个stories
目录。然后根据不同的业务模块创建不同的stories
目录。 比如有个user模块,那么我会创建一个stories/userStory
目录。
// stories/userStory/index.jsx import React from 'react'; import { storiesOf } from '@storybook/react'; import BasicInfo from 'pages/clientDetail/components/BasicInfo'; storiesOf('用户信息', module) .add('基础信息', () => <BasicInfo />); 复制代码
至此,根据 Storybook React Guide ,我们配置了一个简单的storybook环境。 其实这个环境已经可以用了,当然,如果还需要一些额外的功能,比如支持 less
和 scss
等,就需要自定义webpack配置。
storybook 配置
1. 自定义webpack配置
storybook基础webpack配置 只包含以下几项:
- babel
- ES2016+ Support
- .babelrc support
- Webpack
- CSS Support
- Image and Static File Support
- JSON Loader
有时候默认的webpack配置不能满足我们的项目,因此需要对webpack配置进行扩展。
通常我使用的是 Full Control Mode
对webpack配置进行修改。首先在 .storybook
目录下增加 webpack.config.js
文件
const path = require('path'); module.exports = (storybookBaseConfig, configType) => { // 现在应该很多项目会使用`less`或者`scss`等css预处理技术。 // 这里使用了postcss-loader进行处理 storybookBaseConfig.module.rules.push({ test: /\.s?css$/, use: ['style-loader', { loader: 'css-loader', options: { importLoaders: 1 } }, 'postcss-loader'], include: path.resolve(__dirname, '../'), }); return storybookBaseConfig; }; 复制代码
注意 1:默认配置失效
如果使用自定义的配置,默认配置就会失效,如果没有重新配置 file-loader
,storybook运行起来时候假如有控件引用了图片等文件会报错。
// 默认配置会失效,处理文件需要配置相应的file-loader storybookBaseConfig.module.rules.push({ test: /\.(gif|png|jpe?g|eot|woff|ttf|pdf)$/, loader: 'file-loader', }); 复制代码
注意 2:保留原配置上修改
使用 Full Control Mode
模式虽然可以最大限度修改storybook的 webpack
配置,但是以下配置修改时需要注意在原配置上进行扩展。
- entry
- output
- first loader in the module.loaders (Babel loader for JS)
- all existing plugins
比如需要添加一个loader,需要像面那样push一个loader到 module.rules
数组中。
storybookBaseConfig.module.rules.push({ test: /\.s?css$/, use: ['style-loader', { loader: 'css-loader', options: { importLoaders: 1 } }, 'postcss-loader'], include: path.resolve(__dirname, '../'), }); 复制代码
2. storybook + Redux
其实组件可以分为2种,具体可以参照这篇文章
- 展示类,不涉及逻辑只关注样式展示(Presentational)
- 逻辑类,关注逻辑而不涉及样式展示(Container)
展示类
展示类的控件使用Storybook很简单,根据展示类的控件传入props即可。
逻辑类
在我的项目中通常为react-redux connect后的类。类中操作(如网络操作)都是通过redux进行的。 为了让这个类能正常测试运行,需要进行以下操作。(例子均为 userStory
)
- 在story文件中引入react-redux的
provider
和store
。
import { provider } from 'react-redux'; import store from 'store'; 复制代码
- 扩展
story
在storiesOf中增加装饰器,装饰器作用就是把story包裹起来。 因此我们可以利用装饰器的特点把store引入到控件中。
// stories/userStory/index.jsx import React from 'react'; import { provider } from 'react-redux' import { storiesOf } from '@storybook/react'; // 引入store import store from 'store'; import BasicInfo from 'pages/clientDetail/components/BasicInfo'; storiesOf('用户信息', module) .addDecorator(storyFn => <Provider store={store}>{storyFn()}</Provider>) .add('基础信息', () => <BasicInfo />); 复制代码
-
mock数据
团队搭建的 yapi 平台负责mock数据生成。
-
whistle
由于mock数据和storybook不在同一个域,js调用mock数据会跨域,需要做请求转发代理。我们团队使用的是 whistle 。whistle是个好东西:+1:,墙裂推荐!!!
以下是whistle配置的转发规则。
//yourproject.com resCors://* //localhost:8888 resCors://enable //yourproject.com http://127.0.0.1:8888/ weinre:// # 9001是storybook的端口 # https://myapi.xxx.com 是yapi所在域名。 http://localhost:9001/** https://myapi.xxx.com/$1 复制代码
addons
什么是addons,其实可以理解扩展storybook功能的插件。
我使用到的addons有
- addon-actions 用于展示事件处理函数接收到的数据
- addon-console console输出(log、error、warning)
- addon-info 这个最有用了,如果控件填写了proptype,直接就能显示到storybook中。
- addon-viewport 其实就是chrome的device toolbar功能。
注意
addon-actions和addon-viewport都需要在 addons.js
中注册才能使用。
实践
实践代码
这个就是我的 .storybook
目录结构。
. ├── README.md ├── addons.js ├── config.js ├── stories │ └── userStory │ └── index.js └── webpack.config.js 复制代码
-
config.js
import { configure } from '@storybook/react'; import { setConsoleOptions } from '@storybook/addon-console'; import 'index.scss'; setConsoleOptions({ panelExclude: [], }); function loadStories() { require('./stories/userStory'); } configure(loadStories, module); 复制代码
-
webpack.config.js
const path = require('path'); module.exports = (storybookBaseConfig, configType) => { storybookBaseConfig.module.rules.push({ test: /\.s?css$/, use: ['style-loader', { loader: 'css-loader', options: { importLoaders: 1 } }, 'postcss-loader'], include: path.resolve(__dirname, '../'), }); storybookBaseConfig.module.rules.push({ test: /\.(gif|png|jpe?g|eot|woff|ttf|pdf)$/, loader: 'file-loader', }); // 设置别名 storybookBaseConfig.resolve.alias = { antd: path.resolve(__dirname, '..', `node_modules/antd/dist/antd.min.js`), antdcss: path.resolve(__dirname, '..', 'node_modules/antd/dist/antd.min.css'), antdzhCN: path.resolve(__dirname, '..', 'node_modules/antd/lib/locale-provider/zh_CN.js'), }; // 增加src为绝对路径 storybookBaseConfig.resolve.modules.push(path.resolve(__dirname, '..', 'src')); // 使用source-map storybookBaseConfig.devtool = 'source-map'; storybookBaseConfig.mode = 'development'; return storybookBaseConfig; }; 复制代码
-
addons.js
import '@storybook/addon-actions/register'; import '@storybook/addon-viewport/register'; 复制代码
action和viewport addon均需要在addons.js中注册才能正常使用。
-
userStory
import React from 'react'; import { Provider } from 'react-redux'; import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import { withConsole } from '@storybook/addon-console'; import BasicInfo from 'pages/clientDetail/components/BasicInfo'; import KeyActionItem from 'pages/clientDetail/components/KeyAction/KeyActionItem'; import { withInfo } from '@storybook/addon-info'; import store from 'pages/clientDetail/store'; import zhCN from 'antdzhCN'; import { LocaleProvider } from 'antd'; import 'antdcss'; // redux结合 storiesOf('用户信息', module) .addDecorator(withInfo) .addDecorator((storyFn, context) => withConsole()(storyFn)(context)) .addDecorator(storyFn => <Provider store={store}>{storyFn()}</Provider>) .addDecorator(storyFn => <LocaleProvider locale={zhCN}>{storyFn()}</LocaleProvider>) .add('基础信息', () => <BasicInfo />, { info: { text: ` 用户基础信息展示,可进行上下翻页。 `, }, }); storiesOf('行为轨迹item', module) .addDecorator(withInfo) .addDecorator((storyFn, context) => withConsole()(storyFn)(context)) .add('行为轨迹item--课程顾问', () => ( <div style={{ display: 'flex', justifyContent: 'center', paddingTop: '30px' }}> <KeyActionItem time="2018-12-12 12:12:12" user="testUser" role="课程顾问" type="saler" data={[{ title: '备注', content: '备注测试'}]} id={1} onClickDelete={action('onClickDelete')} canDelete /> </div> )) .add('行为轨迹item--客户', () => ( <div style={{ display: 'flex', justifyContent: 'center', paddingTop: '30px' }}> <KeyActionItem time="2018-12-12 12:12:12" user="testUser" role="家长" type="client" data={[{ title: '购买记录', content: '测试购买记录'}]} /> </div> )) .add('行为轨迹item--admin', () => ( <div style={{ display: 'flex', justifyContent: 'center', paddingTop: '30px' }}> <KeyActionItem time="2018-12-12 12:12:12" user="admin" type="admin" data={[{ title: '购买记录', content: '测试购买记录'}]} /> </div> )); 复制代码
实践截图
addons-info控件能把组件的prop信息展示出来
结语
我在本文中介绍了最基本的storybook使用。
- storybook配置
- webpack配置
- redux引入
- addons介绍
文章中介绍的使用方式实在是很简单,希望能安利更多人使用storybook。更多(高大上)storybook的实践可以参考这里storybook实践
参考
以上所述就是小编给大家介绍的《手把手教你快速搭建专属的storybook》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 从0到1搭建推荐策略产品的思考(二):如何搭建?
- Docker搭建disconf环境,三部曲之三:细说搭建过程
- 在Windows下搭建React Native Android开发环境&搭建项目
- 2019最新k8s集群搭建教程 (centos k8s 搭建)
- Python 环境搭建
- 1 - 搭建开发环境
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Dream Machine
M. Mitchell Waldrop / Penguin Books / 2002-8 / USD 16.00
While most people may not be familiar with the name J. C. R. Licklider, he was the guiding spirit behind the greatest revolution of the modern era. At a time when most computers were big, ponderous ma......一起来看看 《The Dream Machine》 这本书的介绍吧!