Создаем собственный блог с помощью Next.js и Strapi



Книга Создаем собственный блог с помощью Next.js и Strapi

В этой статье вы узнаете:


  • о назначении CMS;
  • как использовать Strapi;
  • как с помощью Next.js и Strapi создавать статические сайты.

Введение


Предположим, что вы создаете блог при помощи Next.js. Для добавления в него поста нужно будет сделать следующее:


  • перейти в каталог /pages/article проекта;
  • создать в нем файл 1.js, чтобы Next.js отрисовывал пост при переходе пользователя по маршруту /article/1;
  • в дальнейшем для добавления других постов понадобится создать 2.js, 3.js и т.д.

И хоть такое решение вполне возможно, обратите внимание, что оно постепенно становится все более утомительным, повторяющимся и времязатратным. Для добавления контента нужно будет всякий раз создавать новый файл.


Есть ли способ упростить этот процесс?


Здесь нам поможет CMS (система управления контентом). С помощью нее можно редактировать содержимое сайта без каких-либо затруднений. Прошло то время, когда для внесения простейших правок в сайт приходилось перелопачивать кучу строк кода. Используя CMS, можно изменять или загружать посты всего в несколько кликов.


Одним из известных примеров CMS является Strapi.



Ключевое преимущество CMS в том, что она позволяет автору писать посты без лишних хлопот и использования кода. Для блогеров такой вариант оказывается очень кстати, так как существенно облегчает им работу. 


В общем, если вы хотите упростить управление блогом, то CMS очень пригодится.


Приступим!


CMS


Настройка


Для запуска Strapi выполните в терминале:


Команда для инициализации Strapi

Следующая команда запустит процесс настройки:


Команда для настройки CMS

Вывод:


Вывод в терминале

Как видите, Strapi предлагает настроить проект. Для этого перейдите на страницу localhost:1337/admin и введите учетные данные для запуска CMS.


Ввод регистрационных данных

После создания учетной записи перед вами возникнет следующая страница:


Панель инструментов

С первой страницей мы разобрались. Далее познакомимся с плагином Content-Types.


Content-Types builder


Согласно документации Strapi, это один из важнейших плагинов. Здесь можно создавать коллекции и отдельные типы. Все это мы разберем поочередно. 


В боковой панели кликните по “Content-Types Builder” в категории Plugins.



Сначала мы создадим простой тип коллекции. Для этого кликните “Create new collection type”.



В диалоговом окне пропишите “Display name” как “Article” и кликните “Continue”:



После этого Strapi предложит добавить поля в новый тип коллекции. Создайте поле “Title” и кликните “Finish” для продолжения:


Создание нового поля

Далее кликните “Add another field”, а затем “Rich Text”. Здесь укажите имя “Body”:


Добавление поля Rich Text

Давайте подытожим, что мы сделали к этому моменту:


  • создали тип коллекции “Article”;
  • сообщили Strapi, что в наших статьях будет по два поля;
  • первое поле “Title”, имеющее тип Text;
  • второе поле “Body”, имеющее тип Rich Text.

Это означает, что можно создать коллекцию статей, которые затем будет отрисовывать Next.js.


Осталось только сохранить изменения. Кликните “Save” в верхнем правом углу:



Если все пройдет успешно, в категории Collection Types должен появиться пункт “Articles”.


У нас все получилось!

Все прошло гладко, и теперь у нас есть коллекция “Articles”.


Далее нужно создать отдельный тип. Кликните в боковой панели “Create new single type”.


Создание отдельного типа

Назовите этот тип “About Me” и присвойте ему текстовое поле с именем “Body”:


Создание текстового поля в типе

Кликните “Save”, чтобы завершить внесение изменений. Теперь тип “About Me” должен появиться там же в боковой панели.



На этом этапе мы проделали следующее:


  • сообщили Strapi, что нам нужен отдельный тип с именем “About Me”:
  • этот тип будет содержать всего одно текстовое поле с именем “Body”.

Проще говоря, отдельный тип служит для контента, который не относится к коллекции (например, меню ресторана, страница About Me или футер).


А теперь напишем первую статью.


Написание статей


Кликните в боковой панели “Articles”, а затем “Add New Articles”. Здесь вы можете добавлять новые элементы в коллекцию “Articles”.


Создание статьи

Теперь вы увидите страницу создания записи для коллекции. Внесем сюда какую-нибудь информацию. Поле Rich Text принимает разметку Markdown.


Создание записи

После введения информации в поля кликните “Save”. Когда Strapi сохранит запись, жмите “Publish”.


Публикация статьи

Вывод:


Статья опубликована

Поздравляю! Вы опубликовали свой первый пост!


На этом раздел заканчивается, и мы переходим к типу “About Me”.


Страница About Me


В боковой панели кликните “About Me” и введите в текстовое поле какой-нибудь текст. По завершению нажмите “Save”.


Создание записи в About Me

В завершении опубликуйте созданную запись.


Публикация записи

Вот и все. Далее мы перейдем к извлечению этих данных с помощью запросов GET.


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


После того, как мы написали посты, нам нужно выполнить простой запрос на получение, чтобы отобразить их во фронтенде. Пока выполним запрос GET из командной строки:


Запрос статей через командную строку

Вот результат:


Ошибка!

Вместо списка постов мы получили ошибку 403. Чтобы от нее избавиться, нужно установить публичный доступ в настройках безопасности Strapi.


Для этого кликните по “Settings” в боковой панели.



Далее в разделе “Users & Permissions Plugin” кликните “Roles”:



В разделе “Roles” выберите “Public”:



После этого промотайте вниз к разделу “Permissions”. В выпадающем меню “Application” отметьте следующие опции:


Отметьте эти опции

Таким образом мы сообщили Strapi, что следующая информация должна быть публичной:


  • содержимое отдельного типа “About Me” (то есть действие find);
  • содержимое и количество элементов, находящихся в коллекции “Articles”. Другими словами, действия count, findone и find являются публичными.

Проверим все это. Для получения списка статей выполните в терминале следующую команду:


Получение статей

Ожидаемый вывод:



Как видите, мы получили массив элементов из коллекции “Articles”.


Далее для получения содержимого типа “About Me” выполните:


Получение данных из “About Me”

Ожидаемый вывод:



Отлично! Все работает, как надо.


На этом очередной раздел закончен. Далее мы займемся разработкой фронтенд-части с помощью Next.js, чтобы отображать статьи на веб-странице.


Фронтенд


Установка


Для инициализации проекта Next.js выполните в терминале:


Инициализация репозитория Next.js

Внутри проекта перейдите в файл /pages/index.js и найдите следующий фрагмент кода:


Код, который нужно найти в /pages/index.js

Удалите код между родительскими тегами div. В итоге /pages/index.js должен выглядеть так:


import Head from "next/head";

export default function Home() {
return (
<div>
<Head>
<title>Home</title>
</Head>
<h1>Welcome home!</h1>
</div>
);
}

  • строка 7: устанавливаем заголовок для домашней страницы.

Выполните код. Результат будет следующим:


Вывод кода

Далее мы перейдем к настройке переменных конфигурации.


Переменные конфигурации


Нас интересует переменная url. Она будет указывать на расположение Strapi. В процессе разработки URL-адресом Strapi будет http://localhost:1337/.


В корне проекта создайте каталог config, а в нем файл next.config.js


В этом файле пропишите следующий код:



const production = process.env.NODE_ENV === "production";

export const url = production
? "https://www.yoursite.com"
: "https://localhost:1337";

  • строка 1: логическое значение production будет указывать, находимся ли мы в среде продакшена;
  • строка 3: если да, то переменная url должна иметь значением URL-адрес развернутого экземпляра Strapi. В противном случае она должна указывать на https://localhost:1337/.

Далее мы перейдем к установке необходимых пакетов.


Установка библиотек


Нам потребуется всего один пакет:


  • react-markdown: поскольку посты будут писаться в Markdown, этот пакет займется отрисовкой кода Mardown и его заменой на HTML.

Выполните в терминале:


Установка пакета

Далее займемся отображением списка постов на веб-странице.


Отображение данных


Импортируйте в /pages/index.js созданную ранее переменную url:


Код для внесения в /pages/index.js

Теперь добавьте в конец этого файла следующий код:


export const getStaticProps = async () => {
const data = await fetch(`${url}/articles`);
const list = await data.json();

return {
props: {
list,
},
revalidate: 1,
};
};

  • строка 1: метод getStaticProps дает Next.js команду применить статическую генерацию для получения данных из CMS;
  • строки 2–3: получение списка статей и преобразование этих данных в JSON;
  • строка 6: экспорт списка в виде пропсов.
  • строка 9: свойство revalidate сообщает Next.js, сколько времени нужно ожидать перед повторной генерацией страницы. В данном случае мы будем выполнять повторную генерацию каждую секунду.

Теперь найдите в /pages/index.js следующий код:


Код, который нужно найти в /pages/index.js

Измените его на:


Изменение кода в /pages/index.js

Эта строка позволяет внести пропс list в компонент Home.


Далее найдите в pages/index.js блок return:


Код, который нужно найти в /pages/index.js

Замените его следующим:


return (
<div>
<Head>
<title>Home</title>
</Head>
<h1>Welcome home!</h1>
<ul>
{list.map((item) => (
<li key={item.id}>
<Link href={`/article/${item.id}`}>
<a>{item.Title}</a>
</Link>
</li>
))}
</ul>
</div>
);

  • строка 8: используем map для получения всех элементов массива list.
  • строка 10: при клике каждый элемент будет указывать на URL /article/$id, где $id является ID элемента массива. Кроме того, на этом шаге реализуется динамическая маршрутизация.
  • строка 11: отображаем только поле Title элементов.

Выполните код. Ожидаемый результат:


Вывод кода

Здорово! Код работает. Дополнительно проверим его, добавив еще один пост. Для этого перейдите обратно в панель Admin и добавьте запись в коллекцию “Article”:


Добавление поста в Strapi

После публикации обновите страницу. Результат должен получиться такой:


Вывод кода

Как видите, теперь можно генерировать новые посты без дополнительного написания кода. 


В итоге файл /pages/index.js должен выглядеть так:


import Head from "next/head";
import { url } from "../config/next.config";
import Link from "next/link";
export default function Home({ list }) {
console.log(list);
return (
<div>
<Head>
<title>Home</title>
</Head>
<h1>Welcome home!</h1>
<ul>
{list.map((item) => (
<li key={item.id}>
<Link href={`/article/${item.id}`}>
<a>{item.Title}</a>
</Link>
</li>
))}
</ul>
</div>
);
}
export const getStaticProps = async () => {
const data = await fetch(`${url}/articles`);
const list = await data.json();

return {
props: { list },
revalidate: 1,
};
};

Просмотр статьи


До этого мы реализовали динамическую маршрутизацию. При нажатии по любому элементу он будет перенаправлять на страницу /article/$id. Осталось только обработать этот URL.


Создайте в директории /pages каталог article, а в нем файл [id].js.


В этом файле пропишите следующий код:


Код для /pages/article/[id].js

Выполните код. Ожидаемый результат:


Вывод кода

Теперь поработаем над извлечением и отображением содержимого постов.


Импортируйте в /pages/article/[id].js переменную url и пакет ReactMarkdown:


Код для /pages/article/[id].js

Далее пропишите в конце файла следующий код:


export const getStaticProps = async (context) => {
const data = await fetch(`${url}/articles/${context.params.id}`);
const article = await data.json();

return {
props: { article },
revalidate: 1,
};
};
export async function getStaticPaths() {
const res = await fetch(`${url}/articles`);
const articles = await res.json();

const paths = articles.map((item) => ({
params: { id: item.id.toString() },
}));

return { paths, fallback: false };
}

  • Строка 1: используем статическую генерацию для получения данных. Переменная context позволяет извлечь параметры, находящиеся в URL.
  • Строки 2–3: получаем данные статьи согласно представленному URL. Например, если пользователь находится на /article/3, выполняем запрос на получение статьи с id равным 3.
  • Строка 6: возвращаем данные статьи в качестве пропсов.
  • Строка 7: просим Next.js выполнять инкрементную генерацию сайта каждую секунду.
  • Строка 9: используем getStaticPaths для статической генерации путей.
  • Строка 13: сохраняем все поля id каждого элемента в отдельном массиве.
  • Строка 17: возвращаем список всех путей, которые Next.js нужно сгенерировать. Свойство fallback говорит Next.js отображать ошибку 404, если пользователь переходит по несуществующему пути.

После экспорта всех данных статьи нужно их отобразить. Найдите в /pages/article/[id].js следующий фрагмент кода:


Код, который нужно найти в /pages/article/[id].js

Измените его так:


Код для замены в /pages/article/[id].js

Далее найдите блок return:


Код, который нужно найти в /pages/article/[id].js

Замените его на:


Код для замены в /pages/article/[id].js

  • Строка 3: отображаем Title в элементе заголовка.
  • Строка 4: отображаем тело с помощью компонента ReactMarkdown. Он будет отрисовывать код Markdown и преобразовывать его в HTML.

Выполните код. Ожидаемый результат:


Вывод кода

Как видите, содержимое статьи успешно выводится, и все работает по плану.


В итоге файл /pages/article/[id].js должен выглядеть так:


import { url } from "../../config/next.config";
import ReactMarkdown from "react-markdown";

export default function Article({ article }) {
return (
<div>
<h1>{article.Title}</h1>
<ReactMarkdown>{article.Body}</ReactMarkdown>
</div>
);
}

export const getStaticProps = async (context) => {
const data = await fetch(`${url}/articles/${context.params.id}`);
const article = await data.json();

return {
props: { article },
revalidate: 1,
};
};
export async function getStaticPaths() {
// Вызываем внешнюю конечную точку API для получения постов
const res = await fetch(`${url}/articles`);
const articles = await res.json();

// Получаем на основе постов пути, которые нужно предварительно отрисовать
const paths = articles.map((item) => ({
params: { id: item.id.toString() },
}));

// В процессе сборки мы будем предварительно отрисовывать только эти пути
// { fallback: false } means other routes should 404.
return { paths, fallback: false };
}

Следующим этапом мы проработаем отображение страницы About Me.


Страница About Me


Этот процесс весьма прост. Создайте в каталоге /pages файл about.js.


В этом файле пропишите:


import { url } from "../config/next.config";
export default function About({ data }) {
console.log(data);

return (
<div>
<h1>About the author:</h1>
{data.Body}
</div>
);
}

export const getStaticProps = async () => {
const res = await fetch(`${url}/about-me`);
const data = await res.json();

return {
props: { data },
revalidate: 1,
};
};

  • Строка 1: импортируем переменную url, указывающую на расположение экземпляра Strapi.
  • Строка 2: создаем функциональный компонент React. При этом также вносим пропс data.
  • Строка 8: отображаем поле Body объекта data.
  • Строки 13–21: используем статическую генерацию для получения соответствующих данных. Позже экспортируем эти данные в качестве пропсов.

Теперь перейдите к localhost:3000/about. Ожидаемый вывод:


Вывод кода

Все отлично работает!


Вот репозиторий этого проекта на GitHub.


Заключение


С появлением CMS, подобных Strapi, жизнь блогеров существенно упростилась. Главным образом благодаря тому, что они избавляют автора от необходимости копаться в коде для внесения в посты простых исправлений. Кроме того, CMS совместно с прекрасными фронтенд-инструментами вроде Next.js оказываются идеальным способом организовать блог в короткий промежуток времени.


Благодарю вас за внимание!


742   0  

Comments

    Ничего не найдено.