🇷🇺 Статья на Хабре
🇺🇦 Статья на DOU
Вы уже слышали о новом подходе JAMstack? Возможность писать веб-приложения на любимом фреймворке, управлять контентом из админ панели, а на выходе получать полностью валидные HTML-страницы построенные согласно с самыми последними рекомендациями SEO, PWA и a11y.
Интересно? Тогда вот список рассматриваемых вопросов в этой статье:
- Что это за новый стек и зачем он нужен?
- Как запустить базовое приложение используя Gatsby?
- Работа с Contentful и создание первой порции данных
- Как связать Contentful и Gatsby используя GraphQL?
- Настроить автоматический деплоймент используя Netlify
Как известно: “Всё новое это давно забытое старое” и вот очередное подтверждение ― мода на статические сайты возвращается. Что представлял собой интернет десять лет назад? Это был PHP сервер-рендеринг, который подставлял данные из БД в HTML-шаблоны и отправлял на клиент.
На смену этому подходу пришли JavaScript фреймворки, которые в последние годы представлены святой троицей веба React Angular Vue Аминь. В чем было кардинальное отличие? В скорости и отзывчивости интерфейса, ведь теперь вся логика сайта находилась на клиенте, и на любое движение мышью можно вызывать красивую анимацию с изменением контента, отправкой запросов на API.
Что дальше? JAM предлагает:
- никакого server-side рендеринга, да и вообще убрать сервер как таковой
- никакого client-side рендеринга, долой
<div id=”root”></div>
- компилировать сайт в обычный HTML код, единожды, в момент изменения контента
- размещение сайта на любом файловом хостинге
Клиент всегда получает, заранее отрендеренную страницу с полностью валидной версткой и вопрос о производительности теперь касается только скорости интернет соединения (но конечно же не стоит забывать про коэффициент прямоты рук разработчиков).
JAM это всего лишь подход, средств для которого на рынке уже достаточно, но как известно гвозди можно забивать чем угодно, но я предпочту молоток.
Список лучших инструментов на 2019 год:
Gatsby ― это генератор статических сайтов из React + GraphQL приложений. Почему именно такой выбор, а не Angular или Vue я затрудняюсь ответить, но скорее всего дело в злой статистике, которая говорит что не смотря на все споры, React самый популярный фреймворк последних трех лет (не забросайте меня камнями в комментариях, за это утверждение, на самом деле мне заплатили). Для более наглядного представления create-react-app
компилирует код в JavaScript билд, для дальнейшего рендера при запуске страницы, Gatsby генерирует полноценные HTML-страницы, с валидной версткой, которые показываются как есть, даже с выключенным JS.
Contentful ― система управления контентом на статических страницах. Это WordPress, который не сохраняет связи между шаблонами и данными в БД, а вместо этого меняет данные непосредственно в HTML файлах.
Netlify ― это очень простая в использовании система деплоймента, которая позволяет связать большинство популярных файловых хостингов с JAM приложением, да ещё и на HTTPS протоколе.
Теперь когда определились с инструментами ― можно приступать.
Создаем аккаунт и видим что по умолчанию сервис генерирует образцовый проект, который я рекомендую сразу же удалять, так как по моему субъективному мнению он больше мешает, чем помогает разобраться. Создаем новый бесплатный проект, без генерации примеров.
Система управления контентом базируется на двух сущностях ― Content model, описывающая структуру и типы данных, и непосредственно Content. Для начала создадим простую модель для нашего блога. Content model состоит из типов данных, например для блога типами данных будут: Article, Person.
конечно же можно выбрать любой уровень абстракции, который по душе, например можно упразднить Person и указывать данные об авторе внутри Article, как Article.author_name
Структура моей модели
article/
├── title (Short text)
├── text (Long text)
├── banner (Single media)
└── publishedAt (Date & Time)
person/
├── fullName (Short text)
└── avatar (Single media)
Далее, используя уже созданные типы данных, добавляем контент, для текстов можно использовать SaganIpsum для картинок Unsplash.
Открываем терминал и создаем рабочую среду
## Установка
npm install --global gatsby-cli
## Создание проекта
gatsby new personal-blog
## Для любителей минимализма можно установить Hello World проект
## gatsby new minimal-gatsby https://github.com/gatsbyjs/gatsby-starter-hello-world
## Переходим в папку
cd personal-blog
Структура проекта
personal-blog/
├── gatsby-browser.js
├── gatsby-config.js
├── gatsby-node.js
├── gatsby-ssr.js
├── LICENSE
├── node_modules
├── package.json
├── README.md
└── src
├── components
│ ├── header.js
│ ├── image.js
│ ├── layout.css
│ ├── layout.js
│ └── seo.js
├── images
│ ├── gatsby-astronaut.png
│ └── gatsby-icon.png
└── pages
├── 404.js
├── index.js
└── page-2.js
## Запуск проекта с hot-reloading
gatsby develop
Что получилось? React + GraphQL приложение собираемое с помощью Gatsby, что значит что можно любой старый проект, который долго рендерится перевести в статический HTML сайт и получить прирост в скорости в несколько раз.
## Установка дополнительных пакетов
npm install gatsby-source-contentful dotenv
Создаем файл .env в корне приложения со следующим содержимым:
/* 12-и значный ключ из Contentful → Settings → API keys → Example key 1→ Space ID */
CONTENTFUL_SPACE_ID=xxxxxxxxxxxx
/* 64-х значный ключ из Contentful → Settings → API keys → Example key 1→ Content Delivery API - access token */
CONTENTFUL_ACCESS_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Расширяем конфигурацию в gatsby-config.js:
if (process.env.NODE_ENV === "development") {
require("dotenv").config();
}
module.exports = {
/* other settings */
plugins: [
/* other plugins */
{
resolve: `gatsby-source-contentful`,
options: {
spaceId: process.env.CONTENTFUL_SPACE_ID,
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
},
}
]
}
Перезапускаем Gatsby сервер и если консоль не показывает никаких ошибок, значит соединение с Contentful установлено и можно переходить дальше.
Если Вы еще не знакомы с GraphQL, то не переживайте потому что это достаточно просто. Наш сайт сейчас находится по адресу:
Но мы пока что оставим его и откроем вторую вкладку:
http://localhost:8000/___graphql
Перед нами IDE для GraphQL прямо в браузере. С ним очень удобно строить запросы и тестировать их. Кликните на Docs в верхнем правом углу, чтобы развернуть сайдбар с документацией, но сюрприз, это не документация к GraphQL, это документация Вашего API. Разверните список Query чтобы увидеть все доступные схемы для запросов, с их типами данных.
Интересующие нас схемы имеют примерно следующее название:
contentfulВашТипДанных - один экземпляр
allContentfulВашТипДанных - список экземпляров
Пример моих данных
- contentfulArticle
- contentfulPerson
- allContentfulArticle
- allContentfulPerson
Используя левую панель построим правильный запрос для наших данных (попробуйте автодополнение, очень удобно).
Пример запрашивающий один экземпляр типа Person и список из Article
{
contentfulPerson {
fullName
avatar {
file {
url
}
}
}
allContentfulArticle {
edges {
node {
title
text {
text
}
banner {
file {
url
}
}
publishedAt
}
}
}
}
Что можно отметить из структуры запросов:
- чтобы получить URL для файла, нужно обращаться по пути
typeName.file.url
- чтобы получить текст из типа Long text, идем по пути
typeName.typeName
- чтобы получить список экземпляров какого-то типа нужно использовать следующий путь
allContentfulName.edges
Переносим схему запроса в проект и рендерим их как обычные данные в React-приложении. Общепринятым Best Practice считается использование <StaticQuery />
компонента из пакета gatsby, который уже установлен в проект.
Пример файла index.js
import React from "react"
import { StaticQuery, graphql } from "gatsby"
import Layout from "../components/layout"
import Article from "../components/article"
const IndexPage = () => (
<Layout>
<StaticQuery
query={graphql`
{
allContentfulArticle {
edges {
node {
id
title
text {
text
}
banner {
file {
url
}
}
publishedAt
}
}
}
}
`}
render={({
allContentfulArticle: {
edges
}
}) => (
edges.map(({ node }) => (
<Article key={node.id} content={node} />
))
)}
/>
</Layout>
)
export default IndexPage
Как это работает? В query
передается схема запроса GraphQL, а в render
наш любимый JSX. Используйте деструктуризацию чтобы сделать код более читабельным.
Деструктуризация на примере components/article.js
import React from "react"
const Article = ({
content: {
title,
text,
banner: {
file: {
url
}
},
publishedAt
}
}) => (
<div>
<h2>{title}</h2>
<img src={url} alt={title}/>
<p>
{text}
</p>
<h5>{publishedAt}</h5>
</div>
)
export default Article
Разместим наш проект на GitHub, откуда его можно будет деплоить в следующем шаге.
Для тех кто до сих пор не в курсе как это сделать
## Находясь в папке с проектом инициализируем пустой репозиторий
git init
## Сделаем первый коммит
git add .
git commit -m “initial commit”
## Создаем репозиторий на GitHub и подключаем
git remote add origin [email protected]:yourname/my-repository-name.git
## Публикуем изменения
git push origin master
Создаем аккаунт используя тот сервис, на котором планируется размещение проектов. Я выбрал GitHub, поэтому после успешной авторизации настроим новый проект, клик на New site from Git. Подключаем наш репозиторий, а Netlify автоматически определит что это Gatsby проект и настроит все скрипты для сборки.
Выбираем нужную ветку, и не забываем про переменные окружения, для этого раскрываем меню Advanced settings и добавляем содержимое локального файла .env и подтверждаем настройки.
Пара минут магии и сайт на месте:
https://tender-liskov-ce3ad0.netlify.com
Осталось добавить хук на обновление контента. Переходим в настройки:
Deploy settings → Build hooks → Add build hook Устанавливаем любое понятное название, для примера "Contentful hook", выбираем ветку с которой будем делать билд и подтверждаем. Результатом будет ссылка, копируем и идем в панель Contentful:
Settings → Webhooks
Ищем на правой боковой панели темплейт для Netlify и в два клика связываем две системы. Пробуем изменить контент и смотрим как новые данные появляются на сайте.
JAM-stack совмещает в себе решение проблем предшествующих подходов и похоже претендует на захват власти и всемирную популярность, но революция ли это? Ничего нового и особенного нет, но это самая передовая методология последних двух лет, там, на чужбине, а у нас? Мы только-только начали переводить проекты с WordPress на React и это однозначно прогресс, но может чтобы не остаться за бортом, как легендарный индийский аутсорс, нам пора делать более решительные шаги?