Ви вже чули про новий підхід JAMstack? Нарешті з’явилася можливість створювати веб-додатки на улюбленому React, мати зручну адмінпанель для керування контентом, а на виході отримувати повністю валідні HTML-сторінки, побудовані згідно з останніми рекомендаціями SEO, PWA та a11y.
Цікаво? Тоді ось список тем, розглянутих у статті:
- Що це за новий стек і навіщо він потрібен?
- Як запустити перший проект на Gatsby?
- Contentful для керування даними.
- Як зв’язати Contentful з Gatsby, використовуючи GraphQL?
- Налаштування автоматичного деплойменту з Netlify.
JAMstack
Як відомо: «Все нове, то давно забуте старе», і ось ще одне підтвердження ― статичні сайти повертаються. Що таке web десять років тому? Це був PHP сервер-рендер, який при кожному запиті з клієнта підставляв дані з БД у HTML-шаблони і віддавав сторінку.
На зміну цьому підходу прийшли JavaScript-фреймворки, які в останні роки представлені святою трійцею вебу React, Angular, Vue, амінь. У чому була кардинальна відмінність? У швидкості і чутливості інтерфейсу, адже тепер вся логіка сайту перебудовується на клієнті. І на будь-який рух мишею можна викликати красиву анімацію з одночасною зміною контенту та відправкою запитів на сервер.
Що далі? JAM пропонує:
- ніякого server-side рендерингу, та й взагалі прибрати сервер;
- ніякого client-side рендерингу, ніякого більше
<div id ="root"></div>
; - компілювати сайт у звичайний HTML код один раз, лише в момент зміни контенту;
- розміщення сайту на будь-якому файловому хостингу.
Клієнт завжди отримує заздалегідь відрендерену сторінку з повністю валідною з точки зору SEO структурою. І продуктивність тепер залежить лише від швидкості інтернет-з’єднання клієнта (але, звичайно ж, не варто забувати про те, наскільки прямі руки в розробників).
Інструменти
JAM — це лише підхід, засобів для якого на ринку вже достатньо. Як відомо, цвяхи можна забивати чим завгодно, але я пропоную використовувати молоток.
Список найкращих інструментів на 2019 рік:
Gatsby― це генератор статичних сайтів з React + GraphQL додатків. Чому саме такий вибір, а не Angularабо Vue,я не знаю. Найімовірніше справа у статистиці, яка говорить, що незважаючи на всі суперечки, React — найпопулярніший фреймворк останніх трьох років (не закидайте мене камінням в коментарях за це твердження, насправді мені заплатили). Для більш наочного уявлення: create-react-app
компілює код в JavaScript білд для подальшого рендеру під час старту сторінки. Gatsby генерує повноцінні HTML-сторінки, які показуються як є, навіть з вимкненим JS.
Contentful― система управління контентом на статичних сторінках. Це WordPress, який не зберігає зв’язки між шаблонами і даними в БД, а замість цього змінює дані безпосередньо в HTML-файлах.
Netlify― це дуже проста у використанні система деплойменту, яка дозволяє зв’язати більшість популярних файлових хостингів з JAM додатком та ще й на HTTPS-протоколі.
До справи
Тепер, коли визначилися з інструментами, можна починати.
Contentful
Створюємо аккаунт і бачимо, що автоматично сервіс генерує зразковий проект, який я рекомендую відразу ж видаляти. На мою суб’єктивну думку, він більше заважає, аніж допомагає розібратися. Створюємо новий безкоштовний проект, без генерації зразків.
У цілому система управління базується на двох сутностях — 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.
Gatsby
Відкриваємо термінал і створюємо робоче середовище:
## Встановлення 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
Структура згенерованого проекту
## Запуск проекту с hot-reloading gatsby develop
Що вийшло? React + GraphQL додаток, який збирається за допомогою Gatsby. Це означає, що можна будь-який старий проект, який довго рендериться, перевести в статичний HTML-сайт і отримати приріст у швидкості в кілька разів.
Gatsby+Contentful
## Встановлення додаткових пакетів 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 встановлено і можна переходити далі.
Gatsby+GraphQL+Contentful
Якщо ви ще не знайомі з GraphQL, то не переймайтесь, бо це досить просто. Сайт зараз знаходиться за адресою:
Але поки що залишимо його і відкриємо другу вкладку:
Перед нами IDE для GraphQLпрямо в браузері. З ним дуже зручно будувати запити і тестувати їх. Натисніть на Docs у верхньому правому куті, щоб розгорнути сайдбар з документацією. Але сюрприз, це не документація до GraphQL, це документація вашого API. Розгорніть список Query, щоб побачити всі доступні схеми для запитів, з їхніми типами даних.
Схеми, які нас цікавлять, мають приблизно такі назви:
- contentfulВашТипДаних — один екземпляр
- allContentfulВашТипДаних — список з екземплярів
Зразок моїх даних
Використовуючи ліву панель, побудуємо правильний запит для наших даних (спробуйте автодоповнення, дуже зручно).
Зразок, який запитує один екземпляр типу 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 git@github.com:yourname/my-repository-name.git
## Публикуем изменения
git push origin master
Налаштовуємо Netlify
Створюємо аккаунт, використовуючи той сервіс, на якому планується розміщення проектів. Я вибрав 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,і це однозначно прогрес. Але, може, щоб не залишитися за бортом, як легендарний індійський аутсорс, нам час робити більш рішучі кроки?