构建简单的博客架构

本示例中的博客文章将以本地 Markdown 文件的形式存储在应用目录中(而非从外部数据源获取),因此我们需要从文件系统中读取数据。

本节将逐步指导您创建一个从文件系统读取 Markdown 数据的博客。

创建 Markdown 文件

首先,在项目根目录下新建一个名为 posts 的顶级目录(注意不同于 pages/posts)。在 posts 目录中创建两个文件:pre-rendering.mdssg-ssr.md

将以下代码复制到 posts/pre-rendering.md 中:

---
title: 'Two Forms of Pre-rendering'
date: '2020-01-01'
---
 
Next.js has two forms of pre-rendering: **Static Generation** and **Server-side Rendering**. The difference is in **when** it generates the HTML for a page.
 
- **Static Generation** is the pre-rendering method that generates the HTML at **build time**. The pre-rendered HTML is then _reused_ on each request.
- **Server-side Rendering** is the pre-rendering method that generates the HTML on **each request**.
 
Importantly, Next.js lets you **choose** which pre-rendering form to use for each page. You can create a "hybrid" Next.js app by using Static Generation for most pages and using Server-side Rendering for others.

然后将以下代码复制到 posts/ssg-ssr.md

---
title: 'When to Use Static Generation v.s. Server-side Rendering'
date: '2020-01-02'
---
 
We recommend using **Static Generation** (with and without data) whenever possible because your page can be built once and served by CDN, which makes it much faster than having a server render the page on every request.
 
You can use Static Generation for many types of pages, including:
 
- Marketing pages
- Blog posts
- E-commerce product listings
- Help and documentation
 
You should ask yourself: "Can I pre-render this page **ahead** of a user's request?" If the answer is yes, then you should choose Static Generation.
 
On the other hand, Static Generation is **not** a good idea if you cannot pre-render a page ahead of a user's request. Maybe your page shows frequently updated data, and the page content changes on every request.
 
In that case, you can use **Server-Side Rendering**. It will be slower, but the pre-rendered page will always be up-to-date. Or you can skip pre-rendering and use client-side JavaScript to populate data.

您可能已经注意到,每个 Markdown 文件顶部都有一个包含 titledate 的元数据区域。这称为 YAML Front Matter,可以使用 gray-matter 库进行解析。

安装 gray-matter

首先安装 gray-matter,该库可帮助我们解析每个 Markdown 文件中的元数据。

npm install gray-matter

创建读取文件系统的工具函数

接下来,我们将创建一个用于从文件系统解析数据的工具函数。通过此函数,我们希望实现:

  • 解析每个 Markdown 文件,获取 titledate 和文件名(将用作文章 URL 的 id)。
  • 在首页按日期排序列出数据。

在根目录下创建一个名为 lib 的顶级目录。然后在 lib 中创建 posts.js 文件,并复制以下代码:

import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
 
const postsDirectory = path.join(process.cwd(), 'posts');
 
export function getSortedPostsData() {
  // 获取 /posts 目录下的文件名
  const fileNames = fs.readdirSync(postsDirectory);
  const allPostsData = fileNames.map((fileName) => {
    // 移除 ".md" 后缀获取文章 id
    const id = fileName.replace(/\.md$/, '');
 
    // 读取 Markdown 文件内容
    const fullPath = path.join(postsDirectory, fileName);
    const fileContents = fs.readFileSync(fullPath, 'utf8');
 
    // 使用 gray-matter 解析文章元数据
    const matterResult = matter(fileContents);
 
    // 合并数据与 id
    return {
      id,
      ...matterResult.data,
    };
  });
  // 按日期排序文章
  return allPostsData.sort((a, b) => {
    if (a.date < b.date) {
      return 1;
    } else {
      return -1;
    }
  });
}

注意:

学习 Next.js 无需理解上述代码的具体实现,该函数仅用于使博客示例正常运行。但如果您想深入了解:

  • fs 是 Node.js 模块,用于从文件系统读取文件。
  • path 是 Node.js 模块,用于操作文件路径。
  • matter 是一个用于解析 Markdown 文件元数据的库。
  • 在 Next.js 中,lib 文件夹不像 pages 文件夹有特定命名要求,您可以任意命名。通常约定使用 libutils

获取博客数据

现在博客数据已解析完成,我们需要将其添加到首页(pages/index.js)。可以通过 Next.js 的数据获取方法 getStaticProps() 实现。下一节我们将学习如何实现 getStaticProps()

首页示例

让我们进入下一页继续学习!

On this page