JAMstack: створюємо блог з Gatsby + Contentful + Netlify

Ви вже чули про новий підхід 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, то не переймайтесь, бо це досить просто. Сайт зараз знаходиться за адресою:

http://localhost:8000

Але поки що залишимо його і відкриємо другу вкладку:

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 
 Данный адрес e-mail защищен от спам-ботов, Вам необходимо включить Javascript для его просмотра.
 :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, і це однозначно прогрес. Але, може, щоб не залишитися за бортом, як легендарний індійський аутсорс, нам час робити більш рішучі кроки?

Репозиторій з проектом


Читайте також:

Фишки JAMstack: почему статические сайты превосходят традиционные динамические

Похожие статьи:
Команда українських фахівців виграла міжнародний хакатон NASA Space Apps Challenge 2023. Загалом у ньому брало участь понад 5500 команд з усього...
Впервые с эмоциональным выгоранием столкнулась 6 лет назад. Словно по щелчку, я уволилась с руководящей должности с хорошей...
Ciklum де-юре вийшов з білоруського ринку. Про це DOU повідомили в компанії. Рішення про припинення роботи в білорусі в Ciklum...
IT Education Center объявляет запись новых групп на курсы по Администрированию Linux. Начало обучения с 15.02.16 Программа...
Я бы хотел поделиться своими наблюдениями по поводу культуры проведения собеседований на украинском IT-рынке,...
Яндекс.Метрика