Создание простой архитектуры блога

В нашем примере посты блога будут храниться как локальные markdown-файлы в директории приложения (а не загружаться из внешнего источника данных), поэтому нам нужно будет читать данные из файловой системы.

В этом разделе мы пройдём шаги по созданию блога, который читает markdown-данные из файловой системы.

Создание markdown-файлов

Сначала создайте новую корневую директорию с названием posts (это не то же самое, что pages/posts) в корневой папке проекта. Внутри posts создайте два файла: pre-rendering.md и ssg-ssr.md.

Теперь скопируйте следующий код в posts/pre-rendering.md:

---
title: 'Два вида предварительного рендеринга'
date: '2020-01-01'
---
 
Next.js поддерживает два вида предварительного рендеринга: **Статическую генерацию (Static Generation)** и **Рендеринг на стороне сервера (Server-side Rendering)**. Разница заключается в том, **когда** генерируется HTML для страницы.
 
- **Статическая генерация** — это метод предварительного рендеринга, который генерирует HTML во время **сборки**. Затем предварительно отрендеренный HTML _переиспользуется_ при каждом запросе.
- **Рендеринг на стороне сервера** — это метод предварительного рендеринга, который генерирует HTML при **каждом запросе**.
 
Важно, что Next.js позволяет **выбирать**, какой метод предварительного рендеринга использовать для каждой страницы. Вы можете создать "гибридное" Next.js-приложение, используя статическую генерацию для большинства страниц и рендеринг на стороне сервера для остальных.

Затем скопируйте следующий код в posts/ssg-ssr.md:

---
title: 'Когда использовать статическую генерацию вместо рендеринга на стороне сервера'
date: '2020-01-02'
---
 
Мы рекомендуем использовать **статическую генерацию** (с данными и без) везде, где это возможно, потому что ваша страница может быть собрана один раз и обслуживаться через CDN, что делает её намного быстрее, чем если бы сервер рендерил страницу при каждом запросе.
 
Вы можете использовать статическую генерацию для многих типов страниц, включая:
 
- Маркетинговые страницы
- Посты блога
- Списки товаров в интернет-магазине
- Справку и документацию
 
Спросите себя: "Могу ли я предварительно отрендерить эту страницу **до** запроса пользователя?" Если ответ — да, то вам следует выбрать статическую генерацию.
 
С другой стороны, статическая генерация **не** подходит, если вы не можете предварительно отрендерить страницу до запроса пользователя. Возможно, ваша страница отображает часто обновляемые данные, и её содержимое меняется при каждом запросе.
 
В таком случае вы можете использовать **рендеринг на стороне сервера**. Он будет медленнее, но предварительно отрендеренная страница всегда будет актуальной. Или вы можете отказаться от предварительного рендеринга и использовать клиентский JavaScript для загрузки данных.

Вы могли заметить, что каждый markdown-файл содержит секцию метаданных вверху с полями title и date. Это называется YAML Front Matter, и его можно разобрать с помощью библиотеки gray-matter.

Установка gray-matter

Сначала установите gray-matter, которая позволит нам разбирать метаданные в каждом markdown-файле.

npm install gray-matter

Создание вспомогательной функции для чтения файловой системы

Далее мы создадим вспомогательную функцию для разбора данных из файловой системы. С помощью этой функции мы хотим:

  • Разбирать каждый markdown-файл и получать title, date и имя файла (которое будет использоваться как id для URL поста).
  • Выводить список данных на индексной странице, отсортированный по дате.

Создайте корневую директорию с названием 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, поэтому вы можете назвать её как угодно. Обычно используют lib или utils.

Получение данных блога

Теперь, когда данные блога разобраны, нам нужно добавить их на нашу индексную страницу (pages/index.js). Мы можем сделать это с помощью метода Next.js для получения данных под названием getStaticProps(). В следующем разделе мы узнаем, как реализовать getStaticProps().

Индексная страница

Давайте сделаем это на следующей странице!