Skip to content

鼓励作者:欢迎 star 或打赏犒劳

VuePress 迁移至 VitePress

为什么要从 VuePress 迁移至 VitePress

因为颜值即正义VitepressVuePress 好看太多太多了

安装依赖

依赖说明

  • node 18.x
  • pnpm 7.x
  • vitepress 1.0.0-alpha.46
  • vue 3.2.47
  • vuepress 2.0.0-beta.60 (标注之前用的 VuePress 版本)

创建 .npmrc 文件,配置内容如下(不使用 pnpm 的可以忽略)

sh
auto-install-peers=true

registry=https://registry.npmmirror.com

安装 vitepress 相关依赖

sh
pnpm add -D vitepress vue

修改 package.json 中的 scripts

sh
# dev 命令
npm pkg set scripts.dev="vitepress dev docs --port=8732"
# build 命令
npm pkg set scripts.build="vitepress build docs"

注意点

  • vitepress 修改启动端口需要通过命令行传参 --port=8732
  • public 公共文件
    • vuepressdocs/.vuepress/public 目录
    • vitepressdocs/public 目录
  • 路由
    • vuepress 默认配置下 README.mdindex.md 都会被转换成 index.html
    • vitepress 默认配置下只有 index.md 会被转换成 index.html
  • vuepress 使用的是 navbar,需要修改为 nav
  • vuepress 使用的是 children,需要修改为 items,且 items 是一个对象数组
  • vuepress sidebar 的展开使用的是 collapsible,需要修改为 collapsed
  • 导入代码块
    • vuepress
      • 语法为 @[code](./code/snippet.js)
    • vitepress
      • 语法为 <<< @/code/snippet.js
      • 部分导入使用 VS Code region 语法,不再支持按行号引入

快速修改 README.mdindex.md

安装 globby

sh
pnpm add -D globby

编写重命名脚本

js
import { globby } from 'globby'
import fs from 'node:fs'

const paths = await globby(['docs/**/README.md'])

paths.forEach((path) => {
  fs.rename(path, path.replace(/README\.md/, 'index.md'), (err) => {
    !err && console.log(`${path} 重命名成功`)
  })
})

配置语法对比

js
/* vuepress 写法 */
export default {
  themeConfig: {
    navbar: [
      { text: 'Guide', link: '/guide' },
      {
        text: 'Dropdown Menu',
        children: ['/item-1.md']
      }
    ],
    sidebar: {
      '/guide/': [
        {
          text: 'Guide',
          collapsible: true,
          children: ['/item-1.md']
        }
      ]
    }
  }
}

/* vitepress 写法 */
export default {
  themeConfig: {
    nav: [
      { text: 'Guide', link: '/guide' },
      {
        text: 'Dropdown Menu',
        items: [{ text: 'Item A', link: '/item-1' }]
      }
    ],
    sidebar: {
      '/guide/': [
        {
          text: 'Guide',
          collapsed: false,
          items: [{ text: 'Index', link: '/guide/' }]
        }
      ]
    }
  }
}

配置 vitepress

docs/.vitepress 目录下创建 config.ts 文件

ts
import { defineConfig } from 'vitepress'

export default defineConfig({
  // 打包输出目录
  outDir: '../dist',

  // 站点语言标题等
  lang: 'zh-CN',
  title: '茂茂物语',
  description: '茂茂的成长之路,包含前端常用知识、源码阅读笔记、各种奇淫技巧、日常提效工具等',

  /* 主题配置 */
  themeConfig: {
    i18nRouting: false,

    logo: '/logo.png',

    nav: [],
    sidebar: {},
    /* 右侧大纲配置 */
    outline: {
      level: 'deep',
      label: '本页目录'
    },

    socialLinks: [{ icon: 'github', link: 'https://github.com/maomao1996' }],

    footer: {
      copyright: 'Copyright © 2019-present maomao'
    },

    darkModeSwitchLabel: '外观',
    returnToTopLabel: '返回顶部',
    lastUpdatedText: '上次更新',

    docFooter: {
      prev: '上一篇',
      next: '下一篇'
    }
  }
})

添加自定义样式

docs/.vitepress/theme 目录下创建 index.ts 文件和 index.css

index.ts 文件内容如下

ts
import Theme from 'vitepress/theme'

import './index.css'

export default Theme

通过插槽添加自定义组件

这里用一个访问统计来举 🌰

配置 TS 环境

创建 tsconfig.json

json
{
  "compilerOptions": {
    "outDir": "dist",
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "allowJs": true,
    "strict": true,
    "jsx": "preserve"
  },
  "include": ["env.d.ts", "**/.vitepress/**/*"]
}

创建 env.d.ts

ts
/// <reference types="vitepress/client" />

declare module '*.vue' {
  import { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

编写 Visitor 组件

在目录 docs/.vitepress/theme/components 下创建 Visitor.vue 文件

vue
<script setup lang="ts">
import { useRoute } from 'vitepress'

const route = useRoute()
</script>

<template>
  <img
    class="visitor"
    :src="`https://visitor-badge.laobi.icu/badge?page_id=你的个人标识&p=${route.path}`"
    onerror="this.style.display='none'"
  />
</template>

<style scoped>
.visitor {
  margin-left: 8px;
}
@media (min-width: 768px) and (max-width: 920px) {
  .visitor {
    display: none;
  }
}
</style>

修改 docs/.vitepress/theme/index.ts 文件

ts
import { h, App } from 'vue'
import Theme from 'vitepress/theme'

import Visitor from './components/Visitor.vue'

import './styles/index.scss'

export default Object.assign({}, Theme, {
  Layout: () =>
    h(Theme.Layout, null, {
      /**
       * 相关插槽
       * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/Layout.vue
       */
      'nav-bar-title-after': () => h(Visitor)
    })
})

颜值对比

不得不说差的有点多

首页

VuePress 首页VitePress 首页

内容页

VuePress 内容页VitePress 内容页

VuePress 内容页VitePress 内容页

如有转载或 CV 的请标注本站原文地址