背景随着小程序业务的不断迭代,组件越来越多,导致组件规划不清晰、复用率低、组件重复和代码混乱等UI交互一致性和效率提升需求。对于一个组件库来说,实现功能很重要,清晰的文档更重要。否则,由于团队沟通协调成本高,仍会造成碎片化的情况,无法解决组件重复、代码混乱的问题。太郎电动车提取打包组件库及组件库在线演示文档解决了上述问题。解决方案选择在文档区域。PC和H5都有比较成熟的解决方案框架,比如dumi、VitePress等,但是Taro还没有成熟的解决方案框架。即使是taro官方提供的taro-ui,组件也不够丰富,说明和例子不对应,增加了用户的学习成本。所以我们选择了自己手动搭建组件库。手动构建还有另一个优势。dumi这样的框架虽然成熟,但是整体还是很厚重,里面封装了太多的功能,而且大部分代码都是黑盒。对于大多数团队来说,只会用到它的一些核心功能,做减法很困难而且容易出错。框架代码的黑匣子也给后续维护带来了困难。虽然一开始人工施工比较费工夫,但是后续的维护非常容易。主模块技术栈对于一套组件库,主模块包括三个部分:组件、文档、示例:组件:es模块输出和按需加载是必须的,rollup是最好的选择。在组件编写方面,与业务项目保持一致。使用React,组件更适合使用hooks语法,然后是ts,less是正则项。例子:这里是太郎组件库和普通组件库最大的区别。文档是在浏览器环境下运行的,所以如果要展示组件demo,需要用到Taro框架的打包h5功能。所以启动一个单独的项目来运行演示代码,使用TaroReact。至于如何将文档中的代码导入到demo工程中运行,使用webpack-chain自定义md文件的loader,自己写一个loader来实现。文档:文档为静态页面,构建工具为vite。配置简单,编译速度快。对于markdown内容部分,使用react-markdown等插件进行渲染,根据路由读取不同的文件。右侧的预览使用iframe加载演示项目。目录结构├─config│├─vite//vite配置│└─rollup//rollup配置├─dist//doc打包产品├─docs-dist//文档打包产品├─packages│├─demo//组件Tarodemoproject│├─doc//api文档工程│└─ui//组件库├─tests├─index.html//doc入口文件└─package.json开发dev流程&路由关系添加label组件标签例如:在ui/components下添加tag文件夹,组件入口tag/index.tsx,文档文件tag/README.md,组件打包产品/dist/tag/index.js;doc项目添加相应的route/tag,将渲染菜单路由到左侧。当路由切换到/tag时,通过路由组合的importurl导入tag/README.md文件,将md文件中的内容读取为字符串传递给react-markdown组件,渲染成一个中间文件页;demo项目独立运行,打包成h5页面,通过iframe嵌入右侧。首先添加组件路由对应的页面文件。当doc的路由发生变化时,iframe的路由也会发生变化。同步更改,demo切换到对应的路由页面,即可阅读对应的tag/README.md;demo工程通过自定义markdwon-loader读取tag/README.md文件中编写的示例代码,并引用components,通过配置webpack路径别名,将@hb/rent-taro-components指向组件product/dist/标签/索引.js;demo工程通过自定义markdwon-loader页面输出,将当前文档中的所有示例代码组合成一个可运行的页面,可以实时预览所有示例代码的运行情况。这种架构的优点文档和demo都输出在一个md文件中,维护方便,灵活多个demo代码分开编写,相互独立,清晰简洁右边的demo工程是独立的,如果需要,功能demo小程序各模块可单独发布清晰无黑框,方便后续维护每个模块讲解docdoc目录结构├─src│├─components││├─markdown-render//md文件渲染组件││└─...//其他布局组件│├─guides//引导文档│├─router││├─comp-doc.ts//组件路由│├─guide-doc.ts//引导路由││└─index.ts//统一导出│├─app.less│└─App.tsx//主页└─main.tsx//入口文件routercomp-doc.ts:importButtonfrom'@ui/button/README.md?raw';importTagfrom'@ui/tag/README.md?raw';constcompRoutes=[{name:'BasicComponent',path:'/basic',children:[{name:'Button',path:'/button',component:Button,},{name:'tag',path:'/tag',component:Tag,},],},];exportdefaultcompRoutes;demomo目录结构除了添加自定义加载器外,与标准的Taro项目完全相同。├─config│├─dev.js│├─index.js//Tarowebpack配置│├─markdownloader.js//自定义md文件加载器│└─prod.js├─src│├─pages││└─basic//文件夹路径同doc路由Configuration│├─app.less│├─app.ts│└─index.html└─package.jsonroute&corecodeapp.config.ts:除了/index部分,该路线与doc路线一一对应。exportdefault{pages:['pages/basic/button/index',//pages和index之间的部分对应docroute'pages/basic/tag/index'],...}pages/basic/button/index.tsx:只需要将md文件作为组件导入导出即可。md被markdown-loader解析后,成为可运行的组件。//直接导入组件库中的README.md作为demo组件,代码解析在自定义加载器中完成importDemofrom'@components/button/README.md';exportdefaultDemo;config/index.js:通过webpackChainloader定制。constconfig={h5:{//...webpackChain(chain,webpack){chain.merge({module:{rule:{mdLoader:{test:/\.md$/,use:[{loader:'babel-loader',options:{}},{//导入自定义加载器loader:`${path.join(__dirname,'./markdownLoader.js')}`,options:{}},]}}}})}//...}}uits文件配置通过rollup-plugin-typescript2配置对应的config文件。importRollupTypescriptfrom'rollup-plugin-typescript2';//...plugins:[//...RollupTypescript({tsconfig:resolveFile('config/tsconfig.rollup.json'),}),]按需加载更多通过rollup-plugin-postcss导入打包提取样式文件直接通过rollup-plugin-copymovelessfilestodist(因为对于业务项目,不需要打包成css)importRollupCopyfrom'rollup-plugin-copy';从'rollup-plugin-postcss'导入RollupPostCss;constinputD={};compFiles.forEach((item)=>{constval=item.replace(cwd,'').replace('/packages/ui/src/components/','').replace('/index.tsx','');inputD[`${val}`]=item;});constconfig={input:inputD,plugins:[RollupPostCss({使用:[['less',{javascriptEnabled:true,},],],extract:'index.less',extensions:['.css','.less'],makeAbsoluteExternalsRelative:false,}),RollupCopy({verbose:true,targets:[{src:resolveFile('/packages/ui/src/components/*/*.less'),dest:resolveFile('/dist/styles'),}],}),]}(本文作者:范翔宇)本文由哈尔滨技术团队制作。未经许可,不得商业或非商业目的转载或使用本文内容,转载请注明“内容转载自你好科技团队”。
