React 組件庫搭建指南-開發調試

MDX,文檔生花。javascript

概覽

本文解決開發組件時的預覽以及調試問題,順路解決文檔編寫。css

編寫時徹底沒法進行預覽調試java

此處選擇docz來輔助預覽調試。node

docz基於MDX(Markdown + JSX),能夠在 Markdown 中引入 React 組件,使得一邊編寫文檔,一邊預覽調試成爲了可能。並且得益於 React 組件生態,咱們能夠像編寫應用通常編寫文檔,不只僅是枯燥的文字。docz 也內置了一些組件,好比<Playground>react

本節全部代碼可在倉庫chapter-2分支中獲取。webpack

安裝 docz 以及自定義配置

yarn add docz --dev

yarn add rimraf --dev # 清空目錄的一個輔助庫
複製代碼

增長 npm scriptspackage.jsongit

"scripts": {
  "dev": "docz dev", // 啓動本地開發環境
  "start": "npm run dev", // dev命令別名
  "build:doc": "rimraf doc-site && docz build", // 後續會配置打包出來的文件目錄名爲doc-site,故每次build前刪除
  "preview:doc": "docz serve" // 預覽文檔站點
},
複製代碼

注意:本節全部操做都是針對站點應用。打包指代文檔站點打包,而非組件庫。github

新建doczrc.js配置文件,並寫入如下內容:web

doczrc.jstypescript

export default {
  files: './components/**/*.{md,markdown,mdx}', // 識別的文件後綴
  dest: 'doc-site', // 打包出來的文件目錄名
  title: 'happy-ui', // 站點標題
  typescript: true, // 組件源文件是經過typescript開發,須要打開此選項
};
複製代碼

因爲使用了less做爲樣式預處理器,故須要安裝 less 插件。

yarn add less gatsby-plugin-less --dev
複製代碼

新建gatsby-config.js,並寫入如下內容:

gatsby-config.js

module.exports = {
  plugins: ['gatsby-theme-docz', 'gatsby-plugin-less'],
};
複製代碼

編寫文檔

新建components/alert/index.mdx,並寫入如下內容:

---
name: Alert 警告提示
route: /Alert
menu: 組件 ---

import { Playground } from 'docz'; import Alert from './alert'; // 引入組件 import './style'; // 引入組件樣式

# Alert 警告提示

警告提示,展示須要關注的信息。

## 代碼演示

### 基本用法

<Playground>
  <Alert kind="warning">這是一條警告提示</Alert>
</Playground>

## API

| 屬性 | 說明     | 類型                                         | 默認值 |
| ---- | -------- | -------------------------------------------- | ------ |
| kind | 警告類型 | 'info'/'positive'/'negative'/'warning'非必填 | 'info' |
複製代碼

執行腳本命令:

yarn start # or yarn dev
複製代碼

能夠在localhost:3000看到以下頁面 :

文檔站點

如今能夠在index.mdx中愉快地進行文檔編寫和調試了!

假若本文到了這裏就結束(其實也能夠結束了(_^▽^_)),那我只是官方文檔的翻譯復讀機罷了,有興趣的同窗能夠繼續向下看。

優化文檔編寫

若是代碼演示部分的demo較多(好比基本用法、高級用法以及各類用法等等),在組件複雜的狀況下(畢竟<Alert/>着實太簡單了),會致使文檔很長難以維護,你究竟是在寫文檔呢仍是在寫代碼呢?

那就抽離吧。

components/alert/文件夾下新建demo文件夾,存放咱們在編寫文檔時須要引用的 demo

components/alert/demo/1-demo-basic.tsx

import React from 'react';
import Alert from '../alert';
import '../style';

export default () => <Alert kind="warning"></Alert>;
複製代碼

components/alert/index.mdx

- import Alert from './alert'; // 引入組件
- import './style'; // 引入組件樣式
+ import BasicDemo from './demo/1-demo-basic';

...

<Playground>
- <Alert kind="warning">這是一條警告提示</Alert>
+ <BasicDemo />
</Playground>
複製代碼

這樣咱們就將 demo 與文檔進行了分隔。預覽以下:

文檔重構

等等,你下面顯示的那個<BasicDemo />有點撩人,這裏應該是給用戶爸爸們copydemo源碼,你弄一個標籤在這裏,用戶爸爸確定不開心 🙅‍♀️。

然而<Playground />組件暫時沒法支持上述形式的展現:自定義下方展現的代碼,而非<Playground />內部的代碼。相關討論以下:

其實第一條 PR 已經解決了問題,可是被關閉了,無奈。

不過既然都能引入 React 組件了,在MDX的環境下自定義一個Playground組件又有何難呢,無非就是渲染組件(MDX 自帶)和展現源碼,簡單開放的東西你們都是喜聞樂見的,就叫HappyBox吧。

優化代碼展現

編寫 <HappyBox />組件

安裝依賴:

yarn add react-use antd react-simple-code-editor prismjs react-copy-to-clipboard raw-loader --dev
複製代碼

這些依賴都是服務於文檔站點應用,和組件庫自身毫無關聯。

最終效果以下:

最終效果

根目錄下新建doc-comps文件夾,存放文檔中使用的一些工具組件,好比<HappyBox />

doc-comps

├── happy-box
│   ├── index.less
│   └── index.tsx
└── index.ts
複製代碼

components/doc-comps/happy-box/index.tsx

import React from 'react';
import Editor from 'react-simple-code-editor';
import CopyToClipboard from 'react-copy-to-clipboard';
import useToggle from 'react-use/esm/useToggle';
import { Divider, Typography, Icon, Tooltip, message } from 'antd';
import { highlight, languages } from 'prismjs/components/prism-core';

import 'prismjs/components/prism-clike';
import 'prismjs/components/prism-javascript';
import 'prismjs/components/prism-markup';
import './index.less';

require('prismjs/components/prism-jsx');

const { Text } = Typography;
interface Props {
  code: string;
  title?: React.ReactNode;
  desc?: React.ReactNode;
}

const HappyBox: React.FC<Props> = ({ code, title, desc, children }) => {
  const [isEditVisible, toggleEditVisible] = useToggle(false);

  return (
    <div className="code-box">
      <section className="code-box-demo"> {children}</section>
      <section className="code-box-meta">
        <Divider orientation="left">{title || '示例'}</Divider>
        <div className="code-box-description">
          <Text>{desc || '暫無描述'}</Text>
        </div>
        <Divider dashed></Divider>
        <div className="code-box-action">
          <Tooltip placement="top" title={'複製代碼'}>
            <CopyToClipboard text={code} onCopy={() => message.success('複製成功')}>
              <Icon type="copy" />
            </CopyToClipboard>
          </Tooltip>
          <Tooltip placement="top" title={isEditVisible ? '收起代碼' : '顯示代碼'}>
            <Icon type="code" onClick={toggleEditVisible} />
          </Tooltip>
        </div>
      </section>
      {renderEditor()}
    </div>
  );

  /* 代碼展現區域 */
  function renderEditor() {
    if (!isEditVisible) return null;
    return (
      <div className="container_editor_area">
        <Editor
          readOnly
          value={code}
          onValueChange={() => {}}
          highlight={code => highlight(code, languages.jsx)}
          padding={10}
          className="container__editor"
          style={{
            fontFamily: '"Fira code", "Fira Mono", monospace',
            fontSize: 14,
          }}
        />
      </div>
    );
  }
};

export default HappyBox;
複製代碼

相關配置變動

  • 增長 alias別名,源碼展現相對路徑不夠友好;
  • antd 按需引入,即便是站點應用。

新建gatsby-node.js,寫入如下內容以開啓alias

const path = require('path');

exports.onCreateWebpackConfig = args => {
  args.actions.setWebpackConfig({
    resolve: {
      modules: [path.resolve(__dirname, '../src'), 'node_modules'],
      alias: {
        'happy-ui/lib': path.resolve(__dirname, '../components/'),
      },
    },
  });
};
複製代碼

antd 按需引入,安裝依賴,並配置gatsby-config.js

yarn add babel-plugin-import gatsby-plugin-import --dev
複製代碼

gatsby-config.js

module.exports = {
  plugins: [
    'gatsby-theme-docz',
    'gatsby-plugin-less',
    {
      resolve: 'gatsby-plugin-import',
      options: {
        libraryName: 'antd',
        style: 'css',
      },
    },
  ],
};
複製代碼

tsconfig.json 忽略demo,避免組件庫打包生成types時包含其中:

tsconfig.json

{
  "compilerOptions": {
    "allowJs": false,
    "target": "esnext",
    "module": "commonjs",
    "jsx": "react",
    "declaration": true,
    "outDir": "types",
    "strict": true,
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true
  },
  "include": ["components"],
+ "exclude": ["components/**/demo"]
}
複製代碼

改造相關文件

components/alert/demo/1-demo-basic.tsx

- import Alert from '../alert';
+ import Alert from 'happy-ui/lib/alert';

- import '../style';
+ import 'happy-ui/lib/alert/style';
複製代碼

components/alert/index.mdx

- import { Playground } from 'docz';
+ import { HappyBox } from '../../doc-comps';

+ import BasicDemoCode from '!raw-loader!./demo/1-demo-basic.tsx';

...

- <Playground>
- <BasicDemo />
- </Playground>

+ <HappyBox code={BasicDemoCode} title="基本用法" desc="使用kind控制Alert類型">
+ <BasicDemo />
+ </HappyBox>
複製代碼

其餘

.eslintignore

+ doc-comps
+ demo
複製代碼

yarn start卡住時嘗試刪除根目錄.docz文件夾,然後從新執行命令。

更多詳見倉庫

開發調試與文檔編寫結束,歡迎指點交流。

To be Continued...

相關文章
相關標籤/搜索