×

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: {
        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

Налаштовуємо 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, і це однозначно прогрес. Але, може, щоб не залишитися за бортом, як легендарний індійський аутсорс, нам час робити більш рішучі кроки?

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


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

Детально про Gatsby.js — інструмент для створення складних веб-сайтів

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

Все про українське ІТ в телеграмі — підписуйтеся на канал DOU

👍ПодобаєтьсяСподобалось2
До обраногоВ обраному1
LinkedIn

Схожі статті

  • React Hooks — огляд можливостей нового APIReact Hooks — огляд можливостей нового API

    Symonenko Volodymyr

    Мене звати Володимир Симоненко. Я фронтенд-розробник у компанії PyTeam. Це стаття-огляд нових можливостей відомої та популярної бібліотеки для веб-інтерфейсів React.js і буде більш цікава тим, хто вже знайомий с реактом. 39

  • Vue-типізація legacy Vuex Store: вирішення проблемиVue-типізація legacy Vuex Store: вирішення проблеми

    Коля Коваль

    Вітаю! Мене звати Микола Коваль, я Front-end Team Lead компанії SocialTech, і це моя коротка історія про те, як ми Vuex типізували. У статті я розповім, як просто й безболісно здружити типи компонентів з Vuex за допомогою кількох рядків коду. 1

  • Співбесіда з JavaScript. 300+ запитань для Junior, Middle, SeniorСпівбесіда з JavaScript. 300+ запитань для Junior, Middle, Senior

    Редакція DOU

    Редакція DOU поспілкувалась з розробниками, що проводять технічні співбесіди для різних рівнів JavaScript-спеціалістів, і зібрала приблизний список запитань для кандидатів. У матеріалі є і теоретичні питання, і практичні задачі. 81




12 коментарів

Підписатись на коментаріВідписатись від коментарів Коментарі можуть залишати тільки користувачі з підтвердженими акаунтами.

Исправьте в article.js
content: { title, text: { text }, banner: { file: { url } }, publishedAt }

Спасибо за замечание, исправим

Есть ли аналог Contentful, где можно было бы бесплатно создать больше проектов? Если я правильно понял, на 1 область приходится 1 проект, на free доступе всего 2... Где можно создать больше ?

Не искал подобное, поэтому не подскажу

Netlify супер круті чуваки, в мене купа продакшенів крутиться там, жодних проблем за 3+ роки.

я використовував Gatsby + Netlify + Netlify CMS
можу сказати що у Gatsby купа плагінів, але якість їх не дуже висока.

Найбільша проблема — це додаваня нових елементів. Наприклад, як додати в blog post наступні компоненти?
— галерею з картинками
— рекламний блок
— таблицю

Це риторичне питання. В WordPress є купа плагінів — а тут все ручками доводиться робити.

Ну по перше мені здається що Ви не зовсім вірно розумієте для чого саме створений Gatsby. Я би дав спрощене визначення для нього як: «Багатофункцінональний компілятор React проектів з можливістю підстановки данних з різних ресурсів у фінальний білд, який складається зі статичних HTML файлів». Тобто Gatsby не повинен вирішувати питання «рекламного блоку» або «галереї», бо за це у данному стеку відповідає React. Чи зручно це для Вас конкретно, я не можу сказати бо є комьюніті React для яких створений JAM-stack. І так можливо на WordPress це буде зручніше зробити, але це server-side рендер і PHP.

По-друге як Ви порівнювали якість плагінів? Це суб’ективщина

Проблема в тому що плагінів gatsby-remark-*** мало а ті що є не вирішують багато задач, як-то можливість розпарсити з markdown-а якісь кастомні елементи.

Якщо у мене є блог і як по тексту (inline) хочу вставити рекламний блок, або інтерактивний якийсь віджет, або посилання на інший текст — то як це зробити?

gatsby-remark-*** — створені під кожен тип маркдауну окремо, а якщо Ви очікуєте, що один плагін підтримуватиме всі типи одразу, ну це трохи не правильно)

«Як вставити рекламний блок?» я вже казав вище, що силами Реакту)

[offtop]
перший раз бачу, як на ДОУ використовують collapsible area 0_0 дуже круто

Так, я спеціально попросив)

Підписатись на коментарі