从组件文档引发的惨案 ◤1◢

2,221 阅读6分钟

公司目前有很多后台管理系统,目前代码量都越来越大,在开发的过程中,我们也秉承着提取公共组件,通过复用组件来减少开发工作量,随着公共组件数量的增加,新同事想要快速了解公共组件如何使用,需要到具体的业务页面中去看,这样子学习组件的成本太大,于是就想给每个组件提供一个文档,来解释组件如何使用。

恰巧之前有同事分享过storybook,听闻效果不错,就准备尝试一下~~

storybook

storybook,人如其名,它将实例化的组件称之为story,不同组件的不同实例化组成了一本 ◤故事书◢。每个组件可以有多个故事,故事之间不同一般是因为入参不同,幻化出的组件不同功能。厉害的它还支持很多插件,来扩展这本故事书。

storybook界面

React项目集成storybook

在现有的项目集成storybook,最大的问题是需要将已有的webpack配置和storybook自己的webpack配置集成到一起。

安装storybook

有两种方式(手动和自动),具体可以参考官方文档

我是采用的手动的方式,觉得比较可控一些。

npm install @storybook/react --save-dev

增加配置文件

在根目录创建文件夹.storybook,然后创建config.js,这个配置文件主要是为了告诉storybook哪些文件是story文件。

import { configure } from '@storybook/react';
// 查找src目录下后缀是.stories.js的文件,就是story
configure(require.context('../src', true, /\.stories\.js$/), module);

合并webpack.config.js

storybook要加载你写的组件,需要依赖你的webpack.config.js来编译代码,参考具体文档

因为我们的项目是使用的ant.desgin pro搭建的,查找了一下居然有人解决过这个问题,就参考了github issues中的解决方法。

写一个story

story其实就是引入组件,并实例化组件的过程,具体的代码如下。

import React from 'react';
import {storiesOf} from '@storybook/react';
import { Button } from '@storybook/react/demo'; 

const stories = storiesOf('Button', module);

stories.add(
    'withText',
    () => {
        return <Button>Hello Button</Button>;
    }
).add(
    'withEmoji',() => {
        return <Button><span role="img" aria-label="so cool">😀 😎 👍 💯</span></Button>
    }
);

引入需要的插件

storybook提供的插件有很多,必须要说想要有野心的框架,一定是可以扩展的。story常用的组件有notes,source,knobs等。使用插件的资料如下,参考资料。引入插件的步骤如下:

1)安装npm包

<!--"@storybook/addon-notes": "^5.2.5"-->
yarn add -D @storybook/addons @storybook/addon-notes

2)增加配置文件addons.js

import '@storybook/addon-notes/register-panel';

3)story文件中增加内容

import React from 'react';
import {storiesOf} from '@storybook/react';
import { Button } from '@storybook/react/demo'; 

// notes插件展示的内容
import readme from './readme.md';

const stories = storiesOf('Button', module);
 
stories.add(
    'withText',
    () => {
        return <Button>Hello Button</Button>;
    }
).add(
    'withEmoji',() => {
        return <Button><span role="img" aria-label="so cool">😀 😎 👍 💯</span></Button>
    },
    {
        notes: {markdown: readme},
    }
);

到此为止,storybook集成算是完成了,但是这种展示的形式有点不太方便,对比ant.design的文档页面,组件和说明文档混合在一个页面的效果,更方便,于是手贱的去尝试了docz,结果就被,坑了,坑了,坑了......

docz

docz的宣传语是◤It's never been easier to document your things!◢ 听起来还是蛮诱惑的,而且它只能使用在React技术栈,效果图如下,感觉还是很完美的。

安装docz

我们是在已有项目中集成docz,很简单安装docz的包即可,但也是正是这里导致了一个大坑。

yarn add docz

启动docz,也可以在scripts中增加命令,参考官方文档。

npx docz dev

配置docz

默认docz会去加载mdx文件渲染,但是也提供了一个doczrc.js文件,用来配置差异化的需求。

// doczrc.js
export default {
  // 哪些文件可以被认为是doc文件被加载渲染
  files: '**/*.{md,markdown,mdx}'
  // or files: ['**/*.{md,markdown,mdx}']
}

存在问题

在已有的项目中安装docz会有一个问题,react会出现版本冲突。

因为docz的package.json中,包含peerDependencies,会重新安装react和react-dom,参考issues

"peerDependencies": {
    "react": "^16.8.0",
    "react-dom": "^16.8.0"
},

到此,崩殂...虽然可以用土办法,修复问题,但是我们还有CI工具要去做线上打包部署等,实在是不优雅,放弃了

father

本以为到docz,一切就到此为止了,偶然的机会发现了蚂蚁金服的前端大佬云谦的一次分享,提到了他们自己基于docz和storybook封装了一个组件开发工具,father。名字起得也这么霸气,总有一种被占了便宜的感觉,o(╥﹏╥)o,于是便拿来试了试了,果然痛并快乐着...

需要提一句的是,father的本职不是做文档的,而是包含组件开发、打包、发布和文档生成的集成方案,所以其实单独使用其文档功能,有点大材小用了。

安装

yarn add father

但是,你观察一下安装完之后father和father-build的package.json,就会发现和你当前项目相似的依赖是在是太多了,甚至连ant.design都重新安装了,不知道什么原因,反正项目就是启动不起来了。

所以只能采取骚操作,在src目录下创建package.json,然后执行yarn add father,期望的是不要影响项目的node_modules。

但是还是失望了,因为node_modules是可以按照层级获取的,还是会影响到根目录的node_modules。

于是骚操作再次尝试,在运行yarn start的时候,将src/node_modules移动到根目录,并命名为fatherlibs;运行组件开发的时候,将fatherlibs移动到src目录下,并改名为node_modules。

这里使用到了一个库shelljs,可以模拟shell命令。

启动

启动father,或者同样增加scripts命令。

npx father doc dev

配置文件

father提供了一个.fatherrc.js配置文件,主要是帮助配置打包方法和调整docz文档配置。

export default {
    esm: 'rollup',
    cjs: 'rollup',
    umd: false,
    doc: {
        title: '**项目组件库',
        files: ['components/**/*.mdx'], 
    },
    cssModules: true,
};

到此为止,虽然可以跑起来,但是每次切换本地开发和组件开发的方式,真的也是不太友好!云谦老师的这个库是真好用,只是这里的场景实在不合适,真不怪大佬。


既然在已有项目中集成这些文档工具,如此麻烦,为什么不将组件开发独立出来呢,哈哈,下一次,我将考虑如何使用现有的工具,进行组件库开发,已经做一些简单的脚手架辅助开发。使用docz和father遇到的问题,如果您有好的方法,不吝赐教...