总结一下storybook增加实时交互代码修改显示结果,自动生成API的Demo页的操作。(React+TypeScript架构)
对比图:
vs
第一步,由于我先前使用的storybook是3.4.1,而参考的例子:https://wix-style-react.now.sh/ 是5.3.19,差了两个大版本,为了避免麻烦我先把已用到的相关插件一块升级,涉及:@types/storybook__addon-actions、@types/storybook__react、file-loader、ts-loader。
然后代码原封不动的跑先前的代码没想到也能跑得通,看来storybook的兼容性做得挺好。
第二步就是storybook的逻辑改造了,主要引入了wix-storybook-utils、yoshi、yoshi-config、yoshi-style-dependencies。我将例子中的代码搬过来后并不会自动跑它的story。对比后发现:
1、storybook的config.js里我的是require('glob-loader!./stories.pattern'),示例的是require('../stories');
2、我的文件名story.tsx + 内部import { storiesOf } from '@storybook/react'自动就能被识别,而示例中的story.js只是单纯export default一个对象,再通过stories\index.js文件中的require('../src/xxx/docs/index.story')启动;
3、storybook的webpack.config.js里,示例主要通过
{
test: /\.story\.js$/,
loader: 'wix-storybook-utils/loader',
options: {
storyConfig: {
moduleName: 'wix-style-react',
importFormat: "import { %componentName } from '%moduleName'",
},
},
}
这一块,把它的样式给跑起来的。
第三步代码改造,我需要在尽量不修改原代码的基础上,增加doc文件夹下examples.js和index.story.js两个文件,重点说说后者,因为和原来的写法完全不一样了:
我把示例的 import allComponents from '../../../stories/utils/allComponents' 改成了 import * as allComponents from '../../../index',直接从输出口调,示例里是走stories加了俩我用不到的组件再转到index,绕了个大弯。后来发现如果要用到外用组件,其实在这弯里写也不错。我是单独Import需要的第三方组件,再把它这样处理了const code = config => baseCode({ components: {...allComponents, Checkbox}, ...config });
第四步也是困扰了我近一天的css引入问题,之前webpack能跑起来,但不能引用新版storybook,而新的webpack两边storybook都能跑起来,但是CSS必需引成一个对象,再通过对象.class交给className。如果样式全改成这样引入,那修改的代码量太多了……
于是我试了各种办法:
不行的方法之一,将原webpack的rules加到里面,它会报错说 Rule can only have one result source (provided use and loaders):
{
test: /\.scss$/,
loaders: ["style-loader", "css-loader", "sass-loader"],
include: path.resolve(__dirname, "../")
}
不行的方法之二,在module.exports = ({ config }) => 的处理开头增加push,但是没有任何作用(如果改成第一种形式引入,又会报一样的错):
config.module.rules.push(
{
test: /\.scss$/,
loader: "sass-resources-loader"
}
);
不行的方法之三,我把module.exports的return打印出来,发现了它其实自带css/scss之类的处理,所以将它引用成一个对象的形式能正常使用,但我现在就只想引用成全局的……于是我将它的rules进行各种篡改,uses、loaders、options、oneof全都试了个遍……反正就是二者不兼容,要么没用要么报错。
妥协的处理方法:
经过无数次试验我突然想到,既然css/scss都被你霸占了,那我干脆自创个扩展名tcss,然后加在rules的最后:
{
test: /\.tcss$/,
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }, { loader: 'sass-loader' }]
}
只要一个story引用了这个index.tcss就可以实现全局化css的功能了,而这文件里的内容也很简单,将原本我要的引起来,又不会影响整个组件的打包,还不需要输出,单纯就是给story用就够了:
@import 'index.scss';
@import '../node_modules/simplebar/dist/simplebar.min.css';
@import '../node_modules/@blueprintjs/core/lib/css/blueprint.css';
另外,为了使Playground能用:
1、原组件的Test.tsx只在export后面加了个default;
2、原index.ts改成index.js,内容由export { Test } from './Test'变成export { default } from './Test.tsx';
3、增加index.d.ts,内容只要写import React from 'react';export default class Realtime{}
……说实话,有点得不偿失的感觉,因为Description标签页变相就是个Playground,所以不加的话这些都可以省略。