在项目中使用 vuepress 搭建组件文档踩坑

4,871 阅读6分钟

前言

随着项目规模越来越大,虽然所在公司前端团队的人数不算多,但还是不可避免的重复造轮子。很多弹窗啦,多选按钮组,特定样式的表格,乃至业务组件。以为项目里没有,费劲巴拉的做出来后,发现有人早早写了个组件放在不知名的地方....由是萌生了打造属于项目的组件库文档的想法,个人觉得属于项目的组件库文档还是有几个不错的意义的:

  • 对前端开发言,减少了沟通成本,减少了重复造组件轮子的几率
  • 可以拿已有的组件文档和UI/UX部门与产品部门商(si)讨(bi),在提新需求,与需求变更时,可以参照已有组件设计
  • 对于项目,甚至公司而言,也容易形成具有独特风格,统一风格的产品

为啥不是 vitepress ,公司还在用 vue2.x,项目里用的都是2的语法,不方便移植

为啥不用storybook,英文不好

那么废话不多说,说白了也就是想折腾折腾,打工人的无奈罢了。接下来进入正题。

环境

  • node 包管理工具:推荐 yarn,在我们安装 vuepress 的主题后,跑起来不容易出错。
  • vuepress:vuepress@1.8.2, 就是当前最新版本
  • 主题:在这里推荐两个vuepress主题
    • vuepress-theme-reco,我在项目里用的就是这个主题,功能比较齐全
    • vuepress-theme-hope,看起来非常棒,功能非常多,但是没玩明白,还是大学生(华东师范大学)写的,没拉下脸去问,哈哈

接下来开始讲讲我在公司的项目中是如何使用 vuepress搭建组件文档项目的。当然基本安装,基本配置什么的,移步官网:vuepressvuepress-theme-reco

vuepress 引入 ant-design-vue

vuepress 中是可以书写 vue 的,而且 组件文档的核心就是能写出代码案例,所以,需要能展示出组件,就需要引入项目中的UI组件库,我们公司使用的是 ant-design-vue,这里以 ant-design-vue举例。代码案例后边会讲。

以下问题,可能不止是 ant-design-vueiviewelement-ui,也可能会碰到。按照教程,在 enhanceApp.js 中加入如下代码:

import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css'

export default ({ Vue }) => {
  Vue.use(Antd)
}

vuepress中应该就可以使用 ant-design-vue里边的组件了。可是,启动项目后发现会报这样的错误,Cannot find module 'core-js/library/fn/xxx/xxx'

这里查询了 issues,和大佬进行了一定的讨论,原因呢应该是 UI 组件中依赖的core-js包和vuepress所依赖的core-js包版本不兼容造成的。大佬附带了解决方案,需要在vuepress配置文件config.js中进行如下配置:

module.exports = {
    chainWebpack: config => {
    	config.resolve.alias.set('core-js/library/fn', 'core-js/features')
    }
}

markdown 中使用 vue

基本的用法可以移步官网:在 Markdown 中 使用 Vue

下面说说可能遇到的坑:

比如我们书写如下的md的代码:

**一行加粗的文本**

<a-card title='card标题'>
	<a-button>一段没被加粗的文本</a-button>
</a-card>

它会被渲染成这样:

这是由于 vuepress 的未知原因造成的,在 issuse 中给出了解决方案。就是在外层包裹一层 div:

**一行加粗的文本**

<div>
    <a-card title='card标题'>
    	<a-button>一段没被加粗的文本</a-button>
    </a-card>
</div>

就能显示正常了:

引入项目中的 vue 组件

  • 引入:我们需要拿到具体项目中书写的组件,docs文件夹不会放在src文件夹下吧。首先需要在 config.js 中配置项目源码的别名:

    const path = require('path')
    
    module.exports = {
        configureWebpack: {
            resolve: {
                alias: {
                    '@src': path.resolve(__dirname, '../../src/'),
                }
            }
        }
    }
    

    在获取组件的文件中即可通过import Loading from '@src/components/Loading'的方式引入组件

  • 注册:enhanceApp.js 中,使用语法Vue.component('组件名', component)即可在 vuepress 全局注册组件, 如:Vue.component('Loading',Loading)。由于项目中注册的组件可能会有许多,而且 enhanceApp.js 的功能不止注册组件,因此推荐把组件存入数组,引入到 enhanceApp.js 中后集中注册:

    import components from './config/component'
    
    export default ({ Vue }) => {
        components.forEach(({name, component}) => Vue.component(name, component))
    }
    

编写组件案例

推荐两个插件:

  • vuepress-plugin-demo-code
  • vuepress-plugin-demo-container

我使用的是 vuepress-plugin-demo-container,用法相对而言还算简单,虽然样式没那么符合我的心意,但是基本功能是有的。基本用法参照 快速上手 | Demo Container

大概长这样:

vuepress 中使用 sass

由于项目中的 vue 组件都使用了 sass 样式预处理器,因此想正常引入组件,vuepress 还需要安装 node-sasssass-loader,他可能会出现如下问题:

参考 vuepress 中的 issues,高版本的node-sasssass-loadervuepress版本并不兼容,这个bug在最新版中也没解决。可行的版本是:node-sass@4.14.1sass-loader@7.3.1

由于我司正在使用的node-sasssass-loader恰好版本不算高,所以不会出现上边的错误,这样就可以尝试把文档项目植入到现有项目中了。假如小伙伴们项目中使用的node-sasssass-loader版本不满足条件,可以尝试这个 issues 的讨论中尝试几个点赞量较高的解决方案。

vuepress 使用全局 sass 变量

既然在项目中都使用了 sass 了,那自然避免不了使用 sass 变量,在组件文档中的全局 sass 样式变量文件和具体项目中的sass样式变量文件区分开。比如叫做 _variables.scss ,其内容为:

@import '../../../src/style/common_variables.scss'

这样就能够获取到项目中所有的sass变量,而且即使项目中的全局sass变量更新后,也不需要对这个文件进行维护了。

然后,需要在config.js中进行如下的配置:

module.exports = {
    configureWebpack: {
        resolve: {
            alias: {
                '@styles': path.resolve(__dirname, './styles')
            }
        }
    },
    scss: {
        data: `
        @import "@styles/_variables.scss";
        `
    }
}

引入 vuepress-theme-reco 主题

假如直接通过当前的 package.json, 使用 yarn 命令安装依赖,有时候项目启动后会出现一个玄学bug: global is not defined,这个bug貌似是由于lock文件造成的。需要删除项目中的package-lock.jsonyarn.lock 文件,最好再删除 node_modules 文件夹,使用yarn安装依赖

Unknown Custom Element - <v-#####>

vuepress 中存在这样的bug:有时候浏览器中 VueDevtools插件 打开的时候,页面会报这个错误,导致页面渲染错误,而这个bug到目前版本仍然未得到修复,因此需要在 enhanceApp.js 中插入下面的代码,参考 issues

import pageComponents from '@internal/page-components'

export default ({Vue}) => {
  Object.entries(pageComponents).forEach(([name, component]) =>  Vue.component(name, component))
}

vue 组件中引用局部定义的子组件

假如在 vuepress 中某个组件是长这样:

const ColorCard = {
    template: `
        <div :style='{ backgroundColor: color }'/>
    `,
    props: ['color'],
}
export default {
    props: {
        colorList: { 
            type: Array,
            default: () => []
        }
    },
    components: {
        ColorCard
    }
}

启动时会报如下错误:

You are using the runtime-only build of Vue where the template compiler is not available.

大致意思就是说,组件不是在运行时编译的,结决这个问题只需要在 config.js 中进行如下配置就行:

module.exports = {
    configureWebpack: {
        resolve: {
            alias: {
                'vue$': 'vue/dist/vue.esm.js',
           }
        }
    },
}

参考:You are using the runtime-only build of Vue where the template compiler is not available.

总结

以上基本就是本人在在项目中使用 vuepress搭建项目组件文档时遇到的几个大大小小的坑了, 其它的小坑,配置都可以在官方配置中容易找到。就不一一介绍了。以下是搭建出来的小成果:

希望本篇能够帮助正在使用 vuepress 的你。❤