likes
comments
collection
share

博客搭建 | 五 使用 vitepress

作者站长头像
站长
· 阅读数 55

简述

最初,我的博客使用的vuepress搭建的,使用的是vuepress-theme-reco,功能齐全,布局简洁美观,也花了一些心思在搭建上面,后来reco主题进入2.x的开发中,1.x版本进入稳定版本,作为博客,内容才是关键,vuepress和它的主题都是载体,而在今年开始(也好像是去年),博客在actions中一直报错,大概是旧版本依赖被弃用了,导致博客无法正常更新至线上,所以便考虑升级博客。

reco2.x仍然采用vuepress作为驱动,而尤雨溪推出了vitepress之后,我决定拥抱新技术,在动手中了解新框架。虽然官方说vuepress和vitepress定位不同,没有替代一说,但vite带来的开发体验确实更好,随着文章的增多,vuepress的启动速度与打包速度都不及vitepress。

在这里提示大家,vitepress作为静态文档生成框架,在工作中接触到的无非是生产相关文档,不需要深入了解,所以也提示大家,如果非兴趣所致,不需要在这上面花太长时间。

本篇文章主要是在实践博客搭建中介绍vitepress的一些特性,目标是对reco主题的部分功能进行复刻。

初始化vitepress项目

pnpm add -D vitepress
pnpm vitepress init

安装和初始化后,我们会得到一个基本的项目框架,运行后会看到一个类似vitepress官方文档的页面布局。

项目目录

为了方便实现博客的一些功能,我们将自己的文章内容分为两类,一类是内容页,一类是功能页(文章列表,时间线等),所以在目录中新建 blogspage两个文件夹,那么整体的目录结构为:

.
├─ .vitepress
│  ├─ theme // 主题相关
│  └─ config.mts // 项目配置
├─ blogs // 文章文件夹  // [!code ++]
├─ page // 功能页 // [!code ++]
├─ api-examples.md // 示例md
├─ markdown-examples.md // 示例md
└─ index.md // 示例md
└─ package.json

进行基础配置

.vitepress>config.mts, 这是整个博客的配置文件,要显示什么,怎么显示都需要再其中设置,现在要对其进行基础设置

1. 汉化

// config.mts
export default {
  // 应用级配置选项
  lang: "zh", //中文配置
  markdown: { // vitepress 对md进行了扩展,有些写法有特殊的样式
    container: {
      tipLabel: '提示',
      warningLabel: '警告',
      dangerLabel: '危险',
      infoLabel: '简述',
      detailsLabel: '详细信息'
    }
  },
  themeConfig: { // 主题配置
    lastUpdated: { // 更新时间的显示
      text: '更新于',
      formatOptions: {
        dateStyle: 'medium',
        timeStyle: 'medium'
      }
    },
    search: { // 搜索
      provider: "local",
      options: {
        translations: {
          button: {
            buttonText: "搜索文档",
            buttonAriaLabel: "搜索文档",
          },
          modal: {
            noResultsText: "无法找到相关结果",
            resetButtonTitle: "清除查询条件",
            footer: {
              selectText: "选择",
              navigateText: "切换",
            },
          },
        },
      },
    },
    notFound:{ // 404页
      title: '未找到页面,迷路了~',
      quote: '请检查地址是否正确,或当前页面未开通,点击下方按钮返回首页',
      linkText: '返回首页'
    },
  }
}

汉化内容可以完全按照自己的想法去设置。

2. 导航

在vitepress中,如果项目不设置根目录和源目录,使用默认设置,那么与.vitepress同级的目录为/

// config.mts
export default {
  themeConfig: { // 主题配置
    nav: [
      { text: "主页", link: "/" },
      { text: "分类", link: "/category.md" },
      { text: "标签", link: "/tag.md" },
      { text: "时间线", link: "/timeline.md" },
      { text: "留言板", link: "/messageBoard.md" },
    ],
  }
}

自定义页面

一般在博客首页都会展示文章列表,为了展示相关内容,我们需要自定义一些页面

vitepress在编译时将md文档转成html,也允许我们在像正常的vue项目中使用组件。

这里以博客主页为例

1. 依赖安装

首先我们需要安装vue,其实我们不安装也可以直接使用,只不过编辑器会不断的报错,特别是在ts环境下,很多vue语法会报错,所以需要安装vue,如果在我们自定义中想要使用其他框架也是可以的,这个就见仁见智了。

2. 创建相关文件

.
├─ .vitepress
│  ├─ theme
│  |  ├─ components
|  |  |  ├─ Blog.vue  // [!code ++]
|  |  |  ├─ More... // [!code ++]
|  |  ├─ index.ts // 主题入口
|  |  ├─ posts.data.ts // [!code ++]

Blog.vue 是博客主页的vue文件,可以任意添加一些内容,后面再讲如何获取博客列表。

3. 引入组件

// .vitepress>theme>index.ts
import { h } from 'vue'
import type { Theme } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import Blog from "./components/Blog.vue"; // [!code ++]
import './style.css'

export default {
  extends: DefaultTheme,
  Layout: () => {
    return h(DefaultTheme.Layout, null, {
      // https://vitepress.dev/guide/extending-default-theme#layout-slots
    })
  },
  enhanceApp({ app, router, siteData }) {
    // ...
    app.component("blog", Blog); // [!code ++]
  }
} satisfies Theme

引入代码没什么需要说明的,回头看一下默认初始化出来的index.md中的内容,头部的配置了一些属性,vitepress会读取它们并执行相关操作,比如 layout:home,该属性表明该页面是使用home组件渲染页面,因此,当我们将layout:home替换成layout:blog,博客首页的渲染内容便成了你的组件内容。

官方提供了三种页面布局:doc | home | page ,你可以在 这里 查看他们的详情。

4. 文章列表组件

获取文章列表的方式vitepress也提供了,在第二步创建的posts.data.ts,其内容可直接复制官方代码,这里是说明,大致了解一下就可以。

需要注意的有以下两点:

// posts.data.ts
export default createContentLoader('posts/*.md', { // [!code --]
export default createContentLoader('blogs/**/*.md', { // [!code ++]
  excerpt: true,
  transform(raw): Post[] {
    return raw
      .map(({ url, frontmatter, excerpt }) => ({
        title: frontmatter.title,
        url,
        excerpt,
        date: formatDate(frontmatter.date)
      }))
      .sort((a, b) => b.date.time - a.date.time)
  }
})

在初始化时创建了两个目录,区分了文章和功能页,也是为了这里在获取文章列表时减少不必要的操作

考虑到后期要增加的标签、分类、时间线等功能,所以需魔改一下createContentLoader,这里贴一下代码仅供参考。 ::: details

export default createContentLoader("blogs/**/*.md", {
  transform(raw): BlogData {
    const blogData: BlogData = {
      posts: [],
      tags: [],
      categories: [],
      everyCategoryCount: {},
    };
    raw.forEach(({ url, frontmatter, excerpt }) => {
      if (frontmatter.publish == undefined || frontmatter.publish) {
        if (frontmatter.tags) blogData.tags.push(...frontmatter.tags);
        if (frontmatter.categories) {
          blogData.categories.push(...frontmatter.categories);
          frontmatter.categories.forEach((category: string) => {
            if (blogData.everyCategoryCount[category]) {
              blogData.everyCategoryCount[category]++;
            } else {
              blogData.everyCategoryCount[category] = 1;
            }
          });
        }
        blogData.posts.push({
          title: frontmatter.title,
          url,
          excerpt,
          date: formatDate(frontmatter.date),
          frontmatter,
        });
      }
    });
    blogData.tags = removeDuplicates(blogData.tags) as string[];
    blogData.categories = removeDuplicates(blogData.categories) as string[];
    blogData.posts.sort((a, b) => b.date.time - a.date.time);
    return blogData;
  },
});

::: createContentLoader 将处理并返回文章数组,但使用时,并不需要调用该方法,直接使用导出的data

import { data } from '../posts.data'
// 文章数组
console.log(data.posts)
// 省略

基于此流程,便可以创建更多的自定义页面

5. 重写路由

当把所有的功能页(包括主页index.md)放进page文件夹后,我们在导航配置的路由需要加上前缀/page/,如果点击左上交标题,默认回到路由/,以及在默认打开博客时,都是空白页,vitepress提供了路由的重写,这里我们需要重写page的路由

// config.mts
export default {
  rewrites: {
    'page/(.*)': '(.*)',
  },
}

需要注意的是,路由重写后,我们在nav配置的地址应是重写后的

主题

vitepress定义了一些css变量,并且默认分为深色和浅色两个主题,如果想要自定义主题样式,可以在styles.css中覆盖这些样式,官方css变量,

运行时API

VitePress 提供了几个内置的 API 来让你访问应用程序数据。VitePress 还附带了一些可以在全局范围内使用的内置组件。

useData

可访问到页面相关数据和config.mts中自定义的属性,比如:

export default {
  themeConfig:{
    docCount:10, // [!code ++]
  }
}

上述代码在主题配置中新增定义docCount,这个属性是我用来配置文章列表分页的,然后这样使用:

import { useData } from 'vitepress'
const { theme } = useData()
const docCount: number = theme.value.docCount; // 每页展示文章数量

useRouter

路由示例,进行路由跳转

import { useRouter } from 'vitepress'
const { go } = useRouter()
<div @click="go('/somePageRoute')"></div>

<Content />

<Content /> 组件显示渲染的 md 内容。

<!-- blog.vue -->
<template>
  <h1>Custom Layout!</h1>
  <content />
</template>

总结

通过上述流程,基本将vitepress可能用到的功能使用了一遍,当然还有很多没有讲(目前我还没用到..),感兴趣的可以用它创建自己的主题博客或知识笔记,目前我的博客正在搭建中,也欢迎访问~ 个人博客

转载自:https://juejin.cn/post/7380296428142477312
评论
请登录