[Перевод] Разработка статического блога на Gatsby и Strapi
Статические веб-сайты содержат страницы с неизменным содержимым. Технически — это набор HTML-файлов, которые, для каждого посетителя сайта, выглядят одинаково. В отличие от динамических веб-сайтов, для разработки таких сайтов не нужно серверное программирование или базы данных. Публикация статического веб-сайта проста: файлы выгружают на обыкновенный веб-сервер или в некое хранилище. Два основных преимущества статических веб-сайтов — это безопасность и скорость. Тут нет базы данных, поэтому отсюда нечего красть, и тут нет нужды программно генерировать страницу для каждого запроса, что ускоряет работу.
Для того чтобы упростить создание статических веб-сайтов, создано множество опенсорсных инструментов. Например, это Jekyll, Hugo, Hexo, и другие. Работа по подготовке содержимого сайта ведётся путём редактирования чего-то вроде файлов с разметкой, или через некое API для управления контентом. После того, как данные готовы к публикации, генератор берёт эти данные, внедряет их в шаблоны и создаёт множество HTML-файлов, готовых для публикации.
Сегодня мы расскажем о быстрой разработке проектов с помощью Gatsby — генератора статических прогрессивных веб-приложений, и Strapi — системы управления контентом. В результате после того, как вы освоите это руководство, у вас будет работающий статический блог и масса идей, касающихся его развития.
Статические веб-сайты и прогрессивные веб-приложения
Полагаем, прежде чем продолжать, стоит сказать пару слов о прогрессивных веб-приложениях (Progressive Web Apps, PWA). Это — веб-приложения, интенсивно использующие JavaScript, которые отличаются надёжностью, быстротой и привлекательным внешним видом. PWA, благодаря обеспечиваемой ими скорости работы со страницами, и тому, что пользователям удобно с ними взаимодействовать, стали стандартным способом построения веб-интерфейсов. В результате появилось множество фронтенд-фреймворков, таких, как Angular, Vue, и React.
Мы, зная о плюсах статических веб-сайтов и PWA, задались идеей найти способ использовать одновременно и то и другое. Инструмент, который это позволяет, называется Gatsby.
Что такое Gatsby?
Gatsby — это невероятно быстрый фреймворк для разработки веб-сайтов на React. Он позволяет создавать сайты, основанные на React буквально за считанные минуты. Gatsby подходит для проектов разных масштабов — от блогов до корпоративных веб-сайтов.
Так как проекты, созданные с помощью Gatsby, основаны на React, их страницы, при взаимодействии с ними пользователя, не перезагружаются, что делает такие проекты очень быстрыми. Gatsby поддерживает большой набор плагинов, которые позволяют, в частности, использовать данные из различных источников (это, например, markdown-файлы, различные системы управления контентом, и так далее). Центром системы данных Gatsby является интерфейс «узлов», которые используются для моделирования данных, поступающих в Gatsby.
Этот проект создал Кайл Мэтьюз, он официально выпущен в июле 2017-го и уже используется десятками компаний.
Как уже стало понятно, Gatsby, для того, чтобы он мог генерировать HTML-файлы, нужно откуда-то брать данные для них. В нашем случае источником данных будет Strapi.
Что такое Strapi?
Strapi — это фреймворк для управления контентом, основанный на Node.js. Он позволяет быстро разрабатывать API для работы с данными и занимает промежуточное положение между фреймворком для Node.js и CMS без пользовательского интерфейса. Strapi позволяет разрабатывать API очень быстро, что экономит время.
Strapi имеет расширяемую систему плагинов, он отличается большим набором встроенных возможностей. Среди них — панель администратора, система управления аутентификацией и разрешениями, средства управления контентом, генератор API и так далее.
Strapi — это опенсорсный проект, что выгодно отличает его от других CMS. В частности, это означает, что, во-первых, он полностью бесплатен, а во-вторых — то, что компания, выбравшая Strapi, разворачивает CMS на собственных серверах, то есть данные компании остаются под её полным контролем. Кроме того, Strapi можно настраивать и расширять благодаря системе плагинов.
Описав наши инструменты, приступим к разработке статического блога.
Настройка API с помощью Strapi
Воспользуемся возможностями Strapi для разработки API и добавим в систему данные, которые позже превратятся в страницы блога.
▍Установка Strapi
Для работы Strapi нужны Node 8 (или выше) и MongoDB. Если в вашей системе всё это имеется, можно приступать к установке Strapi с использованием npm:
$ npm i strapi@alpha -g
Обратите внимание на то, что Strapi v3 всё ещё находится на стадии альфа-версии, но нам это подойдёт.
▍Создание проекта Strapi
Создадим директорию gatsby-strapi-tutorial
:
$ mkdir gatsby-strapi-tutorial
Создадим каркас API внутри этой директории, для чего сначала перейдём в эту директорию, а потом выполним там соответствующую команду Strapi:
$ cd gatsby-strapi-tutorial
$ strapi new api
▍Запуск сервера
Для запуска сервера Strapi сначала перейдём в соответствующую подпапку директории проекта:
$ cd api
Затем запустим сервер, основанный на Node.js:
$ strapi start
Теперь, если всё сделано правильно, можно будет посетить панель администрирования проекта, которая расположена по адресу http://localhost:1337/admin.
▍Создание первого пользователя
Добавим первого пользователя со страницы регистрации.
▍Создание типа контента
API Strapi основано на структурах данных, которые называются типами контента (Content Type). Это — эквивалент моделей во фреймворках и типов контента в WordPress.
Создадим тип контента с именем article
и с тремя полями: title
(тип string
), content
(тип text
), и author
(тип relation
, у одного автора может быть несколько статей).
▍Добавление материалов статей
Добавим в базу данных несколько статей. Для того чтобы создать статью, выполните следующую последовательность действий:
- Посетите страницу списка статей.
- Щёлкните
Add New Article
. - Введите данные, ссылку на автора, и отправьте форму.
Создайте, пользуясь тем же подходом, ещё две статьи.
▍Настройка доступа
Из соображений безопасности доступ к API, по умолчанию, ограничен. Для того чтобы открыть доступ, посетите раздел аутентификации и разрешений для роли Guest
, выберите действие Article - find
и сохраните изменения. С этого момента у вас должна появиться возможность запрашивать список статей.
Доступ к API автора так же ограничен. Разрешите анонимный доступ, выбрав действие find
(в разделе Users & Permissions
) и сохранив изменения.
Разработка статического веб-сайта
Теперь, когда API готово, можно приступать к разработке статического веб-сайта.
▍Установка Gatsby и создание проекта
Установим Gatsby CLI следующей командой:
$ npm install --global gatsby-cli
В ранее созданной папке gatsby-strapi-tutorial
создадим новый блог:
$ gatsby new blog
▍Запуск сервера Gatsby в режиме разработки
Перейдём в папку проекта:
$ cd blog
Запустим сервер:
$ gatsby develop
После этого посмотреть веб-сайт, созданный Gatsby, можно будет, перейдя по адресу http://localhost:8000/.
▍Установка плагина для работы с источником данных Strapi
Данные, которые являются основой статического сайта, могут поступать из разных источников. Например, это markdown-файлы, CSV-файлы, материалы из WordPress (работа с которыми возможна благодаря плагину JSON REST API), и так далее.
Для того чтобы Gatsby успешно делал свою работу, ему нужно уметь общаться с различными источниками данных. Поэтому у Gatsby существует особый слой — слой данных, основанный на GraphQL.
Для того, чтобы подключить Gatsby к источнику данных, требуется плагин, предназначенный для работы с этим источником данных. Такой плагин можно разработать самостоятельно, либо подобрать из уже существующих. В этом примере мы, в качестве источника данных, будем использовать Strapi, а значит, нам понадобится плагин источника данных для API, построенных с помощью Strapi. Мы уже разработали такой плагин.
Установим его:
$ npm install --save gatsby-source-strapi
Этот плагин нуждается в некоторой настройке. Замените содержимое файла gatsby-config.js
на следующее:
module.exports = {
siteMetadata: {
title: `Gatsby Default Starter`,
},
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-strapi`,
options: {
apiURL: `http://localhost:1337`,
contentTypes: [ // Список типов контента, которые планируется запрашивать из Gatsby.
`article`,
`user`
]
},
},
],
}
Теперь перезапустите сервер для того, чтобы позволить Gatsby воспринять изменения.
▍Список статей
Для начала нам хочется вывести список статей. Для того чтобы это сделать, добавьте следующее содержимое в существующий файл домашней страницы src/pages/index.js
:
import React from 'react'
import Link from 'gatsby-link'
const IndexPage = ({ data }) => (
Hi people
Welcome to your new Gatsby site.
Now go build something great.
{data.allStrapiArticle.edges.map(document => (
-
{document.node.title}
{document.node.content}
))}
Go to page 2
)
export default IndexPage
export const pageQuery = graphql`
query IndexQuery {
allStrapiArticle {
edges {
node {
id
title
content
}
}
}
}
`
В конце файла мы экспортируем pageQuery
— запрос GraphQL, который позволяет получить полный список статей. Как видите, нам нужны лишь поля id
, title
и content
, и GraphQL позволяет получить именно то, что нам нужно.
Затем мы передаём деструктурированный объект { data }
как параметр IndexPage
и, для получения выводимых данных, перебираем его поле allStrapiArticles
.
Для того, чтобы упростить разработку запросов GraphQL, можно воспользоваться соответствующим интерфейсом Gatsby. Взгляните на него и попробуйте создать несколько запросов.
▍Страница просмотра статьи
Теперь то, что мы делаем, уже похоже на блог, и это хорошо. Однако одной важной вещи всё ещё не хватает: страницы просмотра статьи.
Создадим шаблон, содержащий запрос GraphQL и зададим отображаемое содержимое. Делать это будем в файле src/templates/article.js
:
import React from 'react'
import Link from 'gatsby-link'
const ArticleTemplate = ({ data }) => (
{data.strapiArticle.title}
by {data.strapiArticle.author.username}
{data.strapiArticle.content}
)
export default ArticleTemplate
export const query = graphql`
query ArticleTemplate($id: String!) {
strapiArticle(id: {eq: $id}) {
title
content
author {
id
username
}
}
}
`
Смотрится хорошо, но в данный момент Gatsby не знает, когда нужно выводить этот шаблон. Для каждой статьи нужен собственный URL. Сообщим Gatsby о новых URL с помощью функцииcreatePage.
Для того чтобы это сделать, создадим новую функцию, которая называется makeRequest
и используется для выполнения запроса GraphQL. Затем мы экспортируем функцию, которая называется createPage
, в которой мы получаем список статей и создаём страницу для каждой из них. Делается это всё в файле gatsby-node.js
. Вот что у нас получилось:
const path = require(`path`);
const makeRequest = (graphql, request) => new Promise((resolve, reject) => {
// Запрос для получения данных, используемых при создании страниц.
resolve(
graphql(request).then(result => {
if (result.errors) {
reject(result.errors)
}
return result;
})
)
});
// Реализация функции Gatsby API "createPages". Она вызывается один раз когда
// уровень данных готовится к работе для того, чтобы позволить плагину создать из этих данных страницы
exports.createPages = ({ boundActionCreators, graphql }) => {
const { createPage } = boundActionCreators;
const getArticles = makeRequest(graphql, `
{
allStrapiArticle {
edges {
node {
id
}
}
}
}
`).then(result => {
// Создаём страницы для каждой статьи
result.data.allStrapiArticle.edges.forEach(({ node }) => {
createPage({
path: `/${node.id}`,
component: path.resolve(`src/templates/article.js`),
context: {
id: node.id,
},
})
})
});
// Запрашиваем материалы статей для использования при создании страниц.
return getArticles;
};
Перезапустите сервер Gatsby. Теперь ссылки на статьи должны оказаться рабочими, щелчки по ним будут открывать страницы статей.
▍Страница автора
Статьи пишут авторы. Они заслуживают отдельной страницы. Процесс по созданию страницы автора очень похож на процесс создания страницы статьи. Для начала создадим шаблон в файле src/templates/user.js
:
import React from 'react'
import Link from 'gatsby-link'
const UserTemplate = ({ data }) => (
{data.strapiUser.username}
{data.strapiUser.articles.map(article => (
-
{article.title}
{article.content}
))}
)
export default UserTemplate
export const query = graphql`
query UserTemplate($id: String!) {
strapiUser(id: { eq: $id }) {
id
username
articles {
id
title
content
}
}
}
`
Теперь обновим файл gatsby-node.js
для создания соответствующих ссылок:
const path = require(`path`);
const makeRequest = (graphql, request) => new Promise((resolve, reject) => {
// Запрос для получения данных, используемых при создании страниц.
resolve(
graphql(request).then(result => {
if (result.errors) {
reject(result.errors)
}
return result;
})
)
});
// Реализация функции Gatsby API "createPages". Она вызывается один раз когда
// уровень данных готовится к работе для того, чтобы позволить плагину создать из этих данных страницы
exports.createPages = ({ boundActionCreators, graphql }) => {
const { createPage } = boundActionCreators;
const getArticles = makeRequest(graphql, `
{
allStrapiArticle {
edges {
node {
id
}
}
}
}
`).then(result => {
// Создаём страницы для каждой статьи.
result.data.allStrapiArticle.edges.forEach(({ node }) => {
createPage({
path: `/${node.id}`,
component: path.resolve(`src/templates/article.js`),
context: {
id: node.id,
},
})
})
});
const getAuthors = makeRequest(graphql, `
{
allStrapiUser {
edges {
node {
id
}
}
}
}
`).then(result => {
// Создаём страницы для каждого пользователя.
result.data.allStrapiUser.edges.forEach(({ node }) => {
createPage({
path: `/authors/${node.id}`,
component: path.resolve(`src/templates/user.js`),
context: {
id: node.id,
},
})
})
});
// Запросы материалов статей и данных авторов для использования при создании страниц.
return Promise.all([
getArticles,
getAuthors,
])
};
И наконец, перезагрузим сервер и посетим страницу автора, перейдя на неё со страницы просмотра статьи по соответствующей ссылке.
Итоги
Примите поздравления! Только что вы успешно создали невероятно быстрый и простой в управлении блог! Так как управлением содержимым занимается Strapi, авторы могут писать статьи с помощью приятного интерфейса, а разработчику остаётся лишь периодически перестраивать блог для обновления его содержимого.
Что делать дальше?
Вы вполне можете продолжить работу над этим проектом для того, чтобы изучить полезные возможности Gatsby и Strapi. Сюда можно добавить список авторов, категории статей, систему комментирования на базе Strapi API или Disqus. Кроме того, вы можете, пользуясь предложенной здесь методикой, создавать и другие веб-сайты (интернет-магазины, корпоративные сайты, и так далее).
Когда ваш проект будет готов к работе, вы, возможно, захотите выложить его в интернет. Веб-проекты, сгенерированные Gatsby, можно публиковать, пользуясь средствами сервисов для размещения статических сайтов, таких, как Netlify, S3/Cloudfront, страницы GitHub, страницы GitLab, Heroku, и так далее. API Strapi — это система, основанная на Node.js, поэтому оно может быть развёрнуто на базе Heroku или с используемой любой виртуальной машины Linux с установленным на ней Node.js.
Полную версию кода, который мы тут разбирали, можно найти на GitHub. Для того, чтобы увидеть то, что тут создано, в действии, клонируйте репозиторий, выполните команду npm run setup
, запустите сервер Strapi (перейдите в папку api
и выполните команду strapi start
) и сервер Gatsby (перейдите в папку blog
и выполните команду npm run develop
).
Уважаемые читатели! Как вы создаёте статические веб-сайты? Планируете ли вы использовать связку Gatsby-Strapi в своих проектах?