手把手,如何搭建一个通用组件库?(文档+样式+按需打包) |
您所在的位置:网站首页 › 文档样式库怎么导入 › 手把手,如何搭建一个通用组件库?(文档+样式+按需打包) |
之前的文章# 手把手,如何搭建一个通用组件库,并发布到npm?搭建了一个简单的组件库框架,并发布到了npm。 在文章结果也留了几个个坑, 1.没有样式 2.文档系统也没有 3.组件也不能按需加载 我们今天来一一解决。 样式系统搭建之前,先来看看element-plus的样式。 主要分为几个部分,公共样式,混入函数,每个组件对应的样式。 我看了其他几个库,也大概是这种模式。 先看一下var_scss文件。 通过map定义选项,然后通过map.get来获取对应的值,具体的样式,通过各种函数来进行计算。 大概思路有了,就来搭建我们自己的样式。 首先是全局样式,以及公用样式。 具体的组件样式跟函数,我放在组件同级目录中。 文档系统用的是vitepress。 相比于老大哥vuepress。 vitepress跟vite兼容会更好一些,更轻量一些,但是毕竟比较新,可能坑也会多一些。大家可自行选择。
快速上手,我就不介绍了,官方有详细的说明。
安装好了之后,项目跑起来,就能看到一个简单的文档了。 现在我们就可以直接md在上面写vue语法了。 并不是很方便,对吧——button需要写两次 我们希望的是写一次,既有效果,又能展示代码片段。 所以,引入一个插件——vitepress-theme-demoblock。 markdown: { config(md) { // 这里可以使用markdown-it插件 md.use(demoBlockPlugin, { scriptImports: ["import * as bubuUI from '@/index'"], scriptReplaces: [ { searchValue: /import ({.*}) from 'bubu-ui'/g, replaceValue: (s, s1) => `const ${s1} = bubuUI`, }, ], }); }, },scriptImports里面的配置是将doc文档中的import引入替换成本地文件,这样打包之后就不需要做修改了。开发时请求本地文件,打包后使用npm版本。 注意:vitepress-theme-demoblock插件暂不支持vue3.2.44以后得setup写法。需要使用defineComponent写法,且引入库需要使用单引号。 参考如下。 import { defineComponent, ref } from 'vue'; export default defineComponent({ setup() { const val = ref(false); return { val, }; }, });docs的详细请求,大家可以看一下官方文档。 我当时是直接拷贝了vitepress官网上的配置,然后修改侧边栏菜单。 配置好的文档长这样。
我们使用ui库一般有2种方式。 一种是全局引入。 import BuBuUI from "bubu-ui" app.use(BuBuUI)另一种是按需引入。 我们就只管用,不需要管引入的问题,比如我用bu-button,就自动到对应的包中去拿组件。 import BuButton from "bubu-ui/components/button" app.use(BuButton)所以我们需要,把组件单独打包出来。 我们自己写一个脚本,通过vite的buid方法来构建。 import { defineConfig, build } from 'vite'; build({ build: { // 配置跟vite.config.ts文件基本相同 } })这个只是全局打包,还需要多走一步,就是遍历components文件夹的组件,找到index.ts入口文件,重新执行一遍build打包。 打包出来的文件如下,components中的就是单独打出来的组件包。 到这里,还有个问题,ts文件在src/components中,而打包出来的子组件,在components中。(如果打包的时候指定一样的目录,会相互覆盖) 我的解决方案就是写了个拷贝函数,直接把components下的组件,直接拷贝到src/components中。如果哪位大佬有比较优雅的方式,欢迎指正留言,感谢感谢。 // 如果目标文件夹不存在,创建目标文件夹 if (!fse.existsSync(destPath)) { fse.mkdirSync(destPath); } let files; // 读取源文件夹下的所有文件和子文件夹 try { files = fse.readdirSync(srcPath); } catch (err) { return; } // 遍历所有文件和子文件夹 files.forEach((file) => { // 拼接文件路径 const srcFilePath = join(srcPath, file); const destFilePath = join(destPath, file); // 如果是文件夹,递归复制文件夹 if (fse.statSync(srcFilePath).isDirectory()) { copyFolder(srcFilePath, destFilePath); } else { // 如果是文件,复制文件 fse.copyFileSync(srcFilePath, destFilePath); } });现在单独的组件包也有了,还差最后一步。 按需引入安装unplugin-vue-components,这也是element-plus用的方案。 配置替换规则。 Components({ dts: true, resolvers: [ (componentName) => { if (componentName.startsWith('Bu')) { return { name: componentName, from: `bubu-ui/src/components/${componentName.slice(2)}` } } } ] })作用就是,如果有组件是以Bu开头的,就从ui库的src/components下引入组件。然后通过vue的components方法注册组件。 nihao以上的组件使用方式,就相当于如下写法 nihao import { defineComponent } from "vue" import { BuButton } from "bubu-ui/src/components/button" defineComponent({ components: { BuButton } }) 总结到这里,一个通用的组件库基本算是搭建完成了,也能发布上线使用了。 但是要真正封装出一个好用的ui组件库,还是有很多细节需要实现。 举几个例子 1.element-plus支持手动按需导入 nihao import { ElButton } from "element-plus"他的入口文件,并没有把每个组件都打包进去。 这个有大佬知道怎么弄的,也欢迎联系我,感谢。 2.组件开发过程中的相互引用 在组件开发过程中,如果存在组件相互引用,那么我们最好的方式是开发的时候引用本地,打包上线的时候引用的是对应的模块。 这个就涉及到包模块管理了。 3.element-plus的类型封装 element支持如下2种使用方式,又能当插件,又能当组件。 // 1 import { ElButton } from "element-plus" app.use(ElButton) // 2 import { ElButton } from "element-plus" app.component(ElButton)在element-plus中,在组件上添加了一个install方法,导出的均为组件本身。 先到这吧。 后续如果有新的感悟,或者对架构有新的思考再分享。 如果这篇文章对你有所收获,欢迎点赞评论。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |