文章 文章 posts

VitePress 集成 Strapi 接口实现 SSR 渲染

目标

在 VitePress 中集成 Strapi 数据源,通过 SSR 渲染 文章列表和单篇文章。构建时(Build-time)从 Strapi 拉取数据并生成静态页面,保留 VitePress 的静态化特性。

实现步骤

1. 准备 Strapi 接口

假设 Strapi 提供以下接口:

bash
GET https://cms.example.com/api/articles?populate=*

`

返回数据结构:

json
{
  "data": [
    {
      "id": 1,
      "attributes": {
        "title": "第一篇文章",
        "slug": "first-article",
        "content": "正文内容……"
      }
    }
  ]
}

2. 在 VitePress 构建前拉取数据

创建一个脚本 scripts/fetch-strapi.js,用于在构建前从 Strapi 拉取数据并生成 Markdown 文件。

js
// scripts/fetch-strapi.js
import fs from 'fs';
import path from 'path';
import fetch from 'node-fetch';

const API_URL = 'https://cms.example.com/api/articles?populate=*';
const DOCS_DIR = path.resolve('./docs/articles');

async function main() {
  const res = await fetch(API_URL);
  const json = await res.json();
  const articles = json.data;

  if (!fs.existsSync(DOCS_DIR)) {
    fs.mkdirSync(DOCS_DIR, { recursive: true });
  }

  for (const item of articles) {
    const { title, slug, content } = item.attributes;
    const filePath = path.join(DOCS_DIR, `${slug}.md`);

    const md = `---
title: "${title}"
description: "来自 Strapi 的文章"
---

${content}
`;

    fs.writeFileSync(filePath, md);
  }

  console.log(`✅ 已生成 ${articles.length} 篇文章`);
}

main().catch(console.error);

然后在 package.json 中添加 prebuild 脚本:

json
{
  "scripts": {
    "prebuild": "node scripts/fetch-strapi.js",
    "build": "vitepress build"
  }
}

3. 动态文章路由支持

VitePress 会自动将 docs/articles/slug.md 渲染成以下路由:

代码
/articles/first-article.html

你可以创建 docs/articles/index.md 作为文章列表页:

md
---
title: 文章列表
---

<script setup>
import { ref, onMounted } from 'vue'

const articles = ref([])

onMounted(async () => {
  const res = await fetch('/articles.json')
  articles.value = await res.json()
})
</script>

<ul>
  <li v-for="item in articles" :key="item.slug">
    <a :href="'/articles/' + item.slug">{{ item.title }}</a>
  </li>
</ul>

4. 构建时生成文章索引 JSON(可选)

在 fetch-strapi.js 中生成 /public/articles.json:

js
const PUBLIC_DIR = path.resolve('./docs/.vitepress/public');

fs.writeFileSync(
  path.join(PUBLIC_DIR, 'articles.json'),
  JSON.stringify(
    articles.map(a => ({
      title: a.attributes.title,
      slug: a.attributes.slug,
    })),
    null,
    2
  )
);

5. SSR 渲染与预览

构建完成后:

bash
npm run build
npm run serve

VitePress 会生成静态 HTML:

  • /articles/first-article.html:由 Strapi 内容渲染的文章页面;
  • /articles/index.html:文章列表页(使用客户端 fetch 更新)。

进阶功能:仅拉取部分路由

如果你只想拉取部分页面,可以在脚本中控制接口参数:

js
const res = await fetch(`${API_URL}&pagination[limit]=5`);

目录结构示例

代码
docs/
├─ .vitepress/
│  ├─ config.js
│  └─ public/
│     └─ articles.json
├─ articles/
│  ├─ first-article.md
│  └─ second-article.md
└─ index.md
scripts/
└─ fetch-strapi.js

结果

  • VitePress 在构建时 SSR 渲染 Strapi 内容;
  • 最终输出纯静态 HTML;
  • 可通过 Cloudflare Pages / Vercel / GitHub Pages 部署。
Related 工具组件将在独立客户端岛中继续迁移。