Skip to content

从零开始搭建 VitePress 博客系统

在这篇文章中,我将详细介绍如何使用 VitePress、TypeScript 和 Tailwind CSS 搭建一个功能完整的博客系统。

项目初始化

首先,让我们创建一个新的 VitePress 项目:

bash
npm create vitepress@latest my-blog
cd my-blog
npm install

项目结构设计

我们采用以下目录结构:

docs/
├── .vitepress/
│   ├── config.ts           # VitePress 配置
│   ├── theme/              # 自定义主题
│   │   ├── index.ts        # 主题入口
│   │   ├── Layout.vue      # 布局组件
│   │   ├── style.css       # 自定义样式
│   │   ├── tailwind.css    # Tailwind 样式
│   │   └── components/     # 自定义组件
│   ├── data/               # 数据加载器
│   └── utils/              # 工具函数
├── posts/                  # 博客文章
├── public/                 # 静态资源
└── index.md               # 首页

配置 Tailwind CSS

安装 Tailwind CSS 相关依赖:

bash
npm install -D tailwindcss autoprefixer @tailwindcss/typography

创建 tailwind.config.js

javascript
/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./docs/**/*.{js,ts,vue,md}",
    "./docs/.vitepress/**/*.{js,ts,vue}"
  ],
  darkMode: 'class',
  theme: {
    extend: {}
  },
  plugins: [
    require('@tailwindcss/typography')
  ]
}

自定义主题开发

主题入口文件

docs/.vitepress/theme/index.ts 中:

typescript
import { h } from 'vue'
import type { Theme } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import './style.css'
import './tailwind.css'

export default {
  extends: DefaultTheme,
  Layout: () => {
    return h(DefaultTheme.Layout, null, {
      // 插槽配置
    })
  },
  enhanceApp({ app, router, siteData }) {
    // 注册全局组件
  }
} satisfies Theme

博客列表组件

创建 docs/.vitepress/theme/components/BlogList.vue

vue
<template>
  <div class="blog-list">
    <article
      v-for="post in posts"
      :key="post.url"
      class="blog-card mb-6"
    >
      <h2 class="blog-title">
        <a :href="post.url">{{ post.title }}</a>
      </h2>
      <div class="blog-meta">
        <span>{{ formatDate(post.date) }}</span>
        <span>{{ post.readingTime }} 分钟阅读</span>
      </div>
      <p class="blog-excerpt">{{ post.description }}</p>
      <div class="flex flex-wrap gap-2 mt-4">
        <span v-for="tag in post.tags" :key="tag" class="tag">
          {{ tag }}
        </span>
      </div>
    </article>
  </div>
</template>

<script setup>
import { defineProps } from 'vue'

defineProps({
  posts: {
    type: Array,
    required: true
  }
})

function formatDate(date) {
  return new Date(date).toLocaleDateString('zh-CN')
}
</script>

数据加载器

创建 docs/.vitepress/data/posts.data.js 来自动加载文章:

javascript
import { createContentLoader } from 'vitepress'
import readingTime from 'reading-time'

export default createContentLoader('posts/**/*.md', {
  includeSrc: true,
  transform(rawData) {
    return rawData
      .map(({ url, frontmatter, src }) => {
        const stats = readingTime(src)
        return {
          title: frontmatter.title,
          url,
          date: frontmatter.date,
          description: frontmatter.description,
          tags: frontmatter.tags || [],
          author: frontmatter.author || 'William',
          readingTime: Math.ceil(stats.minutes)
        }
      })
      .filter(post => post.title && post.date)
      .sort((a, b) => new Date(b.date) - new Date(a.date))
  }
})

SEO 优化

在 VitePress 配置中添加 SEO 相关设置:

typescript
export default defineConfig({
  title: 'My Tech Blog',
  description: '分享技术、生活与思考',
  head: [
    ['link', { rel: 'icon', href: '/favicon.ico' }],
    ['meta', { name: 'author', content: 'William' }],
    ['meta', { property: 'og:type', content: 'website' }],
    ['meta', { property: 'og:site_name', content: 'My Tech Blog' }],
    ['meta', { name: 'twitter:card', content: 'summary_large_image' }]
  ]
})

部署配置

GitHub Pages 部署

创建 .github/workflows/deploy.yml

yaml
name: Deploy VitePress site to Pages

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        
      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 18
          cache: npm
          
      - name: Install dependencies
        run: npm ci
        
      - name: Build
        run: npm run docs:build
        
      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: docs/.vitepress/dist

VPS 部署

对于 VPS 部署,可以使用 Nginx:

nginx
server {
    listen 80;
    server_name yourdomain.com;
    root /var/www/blog/dist;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

性能优化

图片优化

typescript
// vitepress config
export default defineConfig({
  vite: {
    plugins: [
      // 图片压缩插件
    ]
  }
})

构建优化

typescript
export default defineConfig({
  vite: {
    build: {
      rollupOptions: {
        output: {
          chunkFileNames: 'assets/js/[name]-[hash].js',
          entryFileNames: 'assets/js/[name]-[hash].js',
          assetFileNames: 'assets/[ext]/[name]-[hash].[ext]'
        }
      }
    }
  }
})

总结

通过以上步骤,我们成功搭建了一个功能完整的 VitePress 博客系统,具备以下特性:

  • ✅ 现代化的技术栈
  • ✅ 响应式设计
  • ✅ SEO 优化
  • ✅ 自动化部署
  • ✅ 性能优化

这个博客系统不仅性能优秀,而且易于维护和扩展。希望这篇文章能够帮助你快速上手 VitePress 博客开发!

相关资源

Part of the TimeTofu ecosystem - helping you invest your attention wisely.