解析Markdown文件生成React组件文档
前言
最近做的項目使用了微前端框架single-spa。
對于這類微前端框架而言,通常有個utility應用,也就是公共應用,里面是各個子應用之間可以共用的一些公共組件或者方法。
對于一個團隊而言,項目中公共組件和方法的使用難點不在于封裝不在于技術,很多時候在于團隊內部成員是否都能了解這些組件,以避免重復開發(fā),從而提升團隊效率。
如果是團隊比較小,人員比較穩(wěn)定的項目組可能還好點,對于團隊比較大,人員流動較快的團隊,這些通用組件和方法往往就被人遺忘在角落,很難再得到有效利用。
因為我所在的項目還在開發(fā)初期,并且是新入職也想去熟悉一下當前項目中的一些通用組件和方法,所以我自己特意開發(fā)了一個文檔應用去解決這個問題。
技術方案選型
對于一個面向Ant Design編程的咸魚而言,這個文檔應用肯定是往這個方向做。
目標是能做成Ant Design的組件文檔那樣好用,既能很快看清組件的使用效果,也能快速復制示例代碼。
有了目標之后,很快選定了兩個技術方案
- StoryBook方案
- 自己開發(fā)解析markdown文件的文檔應用
StoryBook是市面上一款比較流行的構建UI組件和文檔的庫,功能很強大。
但是這個庫如果要應用到我們項目的團隊存在以下問題:
- 英文文檔,有學習成本
- 引入single-spa的utility應用很麻煩
- 對于構建在utility應用中的組件,需要在StoryBook中再寫一遍,容易不同步
- 對于通用方法可能不支持
尤其是第三點特別存在問題,團隊成員大都是業(yè)務開發(fā),有交付壓力,不是在github上為愛發(fā)電的開源貢獻者。
他們是否有意愿在utility應用中寫了一遍組件代碼后,又專門跑到這個StoryBook中再寫一道?
如果組件代碼修改后,StoryBook這邊沒修改,這種不同步很容易導致開發(fā)人員明明按照文檔使用組件,但是組件就是報錯,挫敗感很強。
聯(lián)系到現(xiàn)實,我已經(jīng)預想到如果走這個方案,一個月內這個玩意就會名存實亡,成為形式主義的存在,在三個月后成為大家都不愿提起的垃圾了。
所以有了第二個方案的誕生:自己開發(fā)解析markdown文件的文檔應用。
這個方案并不是我憑空想象出來的,而是在前公司中就有這么一個內部應用,組件開發(fā)人員自己編寫markdown文件,最終生成組件文檔,并且應用本身可以解析markdown文件中的代碼部分,從而在組件文檔中生成對應的組件示例。
彼時我只是一個組件開發(fā)人員,并不是這個文檔應用的實現(xiàn)人員,所以也不知道其技術原理。
但是前公司這個應用讓我知道了這么玩行得通,當時作為組件開發(fā)人員,接受和使用這個應用異常輕松,只要會寫markdown就行了,沒有學習成本。而且使用這種方式,控制權掌握在自己手中,更容易和自己的團隊項目有效結合起來。
基本原理
雖然這個文檔應用是我一個人花了兩天的時間獨立完成,但是花的是工作時間,完成后也是公司內部項目,所以這個文檔應用我沒法開源出來。
不過我可以告訴大家一個主要思路和步驟,想必復現(xiàn)出來也并不困難。
第一步讓我們搞定這個項目的框架。
因為需要引入single-spa的utility應用,所以框架我直接用的是single-spa的基座,并且項目內含一個子應用用于展示文檔。而utility應用直接引入線上開發(fā)環(huán)境的utility應用,避免團隊成員重復書寫組件代碼,也解決了文檔和實際應用不同步的問題。
通過這一步,我們解決了StoryBook方案中的痛點2和痛點3。
第二步我們需要載入markdown文件。
這一步肯定是通過webpack的加載器來做處理,這些加載器有的比較強大,可以直接將markdown文件轉換為html。但是我并沒有選擇這種,而是直接用的raw-loader,將我們的markdown文件轉換為字符串載入。
代碼大致如下,這個比較簡單,就不說了。
module.exports = {module: {rules: [{test: /\.md$/,use: 'raw-loader'}]} }第三步我們需要解析markdown文件生成文檔,并解析其中的React組件,生成組件示例。
解析markdown文件轉換為html文檔,實際上有個比較強大的庫,叫Showdown。
而我所用到的庫react-showdown則是對Showdown的進一步封裝,可以借助一個react組件將markdown和包含在markdown文件中的react組件渲染成html。
下面是它的一個官方示例:
import React from 'react'; import MarkdownView from 'react-showdown';export default function App() {const markdown = `# Welcome to React Showdown :+1:To get started, edit the markdown in \`example/src/App.tsx\`.| Column 1 | Column 2 ||----------|----------|| A1 | B1 || A2 | B2 |`;return (<MarkdownViewmarkdown={markdown}options={{ tables: true, emoji: true }}/>); };通過MarkdownView這個組件,可以將一串markdown格式的文本轉化為html。
另外我們注意到它的選項,tables為true,如果不設置這個的話,markdown中的table格式將不會被轉化成表格。第二個emoji為true是支持emoji轉換。
這個時候你可能要問,這只是轉換了一下markdown文件而已,轉換react組件呢?
我們可以看一下下面這個官方示例:
import MarkdownView from 'react-showdown';function CustomComponent({ name }: { name: string }) {return <span>Hello {name}!</span>; }const markdown = ` # 我是個標題:<CustomComponent name="world" />`;<MarkdownView markdown={markdown} components={{ CustomComponent }} />在markdown文本中可以直接寫上CustomComponent這個自定義的react組件代碼,然后在MarkdownView的components中傳入CustomComponent即可。
生成的最終html中不僅會有個標題,標題下面還會展示一個叫hello world!的文本,而不是展示<CustomComponent name="world" />這個字符串。
排疑解難
看完了上面的原理,想必您已經(jīng)可以實現(xiàn)這樣的一個文檔應用了。
不過在這個過程中您可能還是會遇到一些小麻煩,這里提前給您支個招。
麻煩1:markdown轉換成html后的代碼高亮處理。
因為我們做的是一個組件文檔,那么肯定會涉及到代碼展示。
markdown文件中的代碼塊,使用react-showndown轉換后的并沒有做高亮處理。
不過react-showdown是支持Showdown的各種擴展的,其中有個擴展叫showdown-highlight,通過這個擴展可以對代碼塊做高亮處理。
麻煩2:react-showndown只支持簡單的組件。
雖然react-showndown可以解析react組件代碼,但是它也只能簡單解析這個組件。如果我們演示的示例比較復雜,涉及到一些函數(shù),還有一些庫的引用,很顯然不能再markdown文件中直接寫。
這里我建議直接將每個組件的示例寫到一個獨立的js中,這個js導出一個Demo組件,然后我們在markdown文件中直接引用這個demo組件即可。
大致代碼如下:
import MarkdownView from 'react-showdown'; import ButtonDemo from './ButtonDemo';const markdown = ` # 按鈕組件組件描述## 代碼示例<ButtonDemo />```tsx 這里貼出以ButtonDemo組件中的代碼 ```## API| 屬性 | 說明 |XXX| |----------|----------|-----| | title | 按鈕文本 | XXX | | type | 按鈕類型 | XXX |`;<MarkdownView markdown={markdown} components={{ ButtonDemo }} />通過上面這種方式,不論我們ButtonDemo中的邏輯和功能多么復雜,展示出來都是沒問題的。
麻煩3:如何將這個文檔應用做到簡單好用。
看了上面的代碼,可能有人會覺得應該沒問題了。
但是我們得明白,我們這個東西是做給業(yè)務開發(fā)的人員用的,而不是做給我們自己用的。
我業(yè)務開發(fā)人員為什么要知道你這些什么 react-showdown 的代碼?我業(yè)務開發(fā)人員還要學習你的這些鬼東西?不是每個人都想著學這些亂七八糟的技術好嗎?我每天就只想在6點下班,就算你5分鐘內給我講明白了,你這個文檔應用我用不用還兩說。你要是5分鐘之內還講不明白怎么用,那你休想我在這上面給一個公共組件寫文檔。我們面對的基本就是這么一個場景,我們做這個應用是為了解決項目中實際面臨的問題,是面向業(yè)務開發(fā)人員編程,而不是面向領導和KPI編程。
所以我們需要做到簡單好用,將所有涉及到react-showdown這玩意的部分全部不被業(yè)務開發(fā)人員感知。
想象一下,寫一個組件的文檔,縮減到最少,就是一個markdown文件,和一個demo.js。
那么我們就只讓業(yè)務開發(fā)人員去寫這兩個東西就行,把他們的工作量減少到最小。
就給他們兩個文件夾,一個文件夾叫doc,里面放markdown文件,一個文件夾叫demo,里面放各個demo。
再用一個字典配置dict.js,去做個基本的配置。
如果現(xiàn)在有個Easy組件要寫文檔,那么我們的dict.js內容可能就是下面這樣:
const dict=['Easy','Hard','XXX']export defalt dict只需要加個字符串Easy即可。
然后你可以在那么doc文件夾下加個markdown文件叫EasyMD.md,demo文件夾下加個文件叫EasyDemo.tsx。
之后的所有步驟全部由我們的文檔應用解析dict.js后自動完成,無需用戶操心。
通過這樣的一種約定,我們可以將業(yè)務開發(fā)人員的工作量減到最小,把他們寫組件文檔的門檻降到最低。
具體代碼實現(xiàn)就略過了,實現(xiàn)的關鍵詞叫:import()函數(shù),其他的不用多說了。
總結
雖然說這個文檔應用是受前公司啟發(fā),而且因為開發(fā)時間就兩天,所以比較簡陋,但是至少我做到了比前公司的內部應用更簡單方便,完全沒有學習成本。
好了,自吹一波就得了,本篇博客到此結束。
如有疏漏之處,還請不吝賜教。
總結
以上是生活随笔為你收集整理的解析Markdown文件生成React组件文档的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通过Wireshark抓包分析谈谈DNS
- 下一篇: 分布式服务下,消息中间件改造