Использование форм и функций Netlify для создания виджета подписки на рассылку

Бессерверная функция (иногда называемая облачной функцией) – это фрагмент кода, который можно написать, разместить и запустить вне сайта или приложения. На самом деле эти функции выполняются на сервере. Но вам не нужно создавать его или поддерживать.

Задача: создать форму подписки на рассылку

Для своего сайта я хочу создать форму подписки на рассылку. Условия задачи следующие:

  • Форма должна работать без JavaScript – используя только CSS и HTML.
  • Форма не должна иметь внешних зависимостей.
  • Форма должна использовать бессерверные функции. Вместо отправки данных на сервис рассылки сделаем это с помощью бессерверных функций.

Познакомьтесь с командой: 11ty, Netlify и Buttondown

Мой ресурс построен с использованием статического генератора сайтов 11ty. Он позволяет разрабатывать шаблоны и компоненты на HTML. В нем мы и создадим нашу форму.

За развертывание сайта отвечает сервис Netlify. Он позволяет нам воспользоваться преимуществами бессерверных технологий:

  • Netlify может развертываться автоматически из репозитория GitHub. Я могу написать свой код, выполнить pull-запрос и проверить его работоспособность. Существуют инструменты для локального тестирования бессерверных функций, но Netlify упрощает тестирование в режиме онлайн.
  • Формы Netlify обрабатывают всю отправку данных. Вместо написания кода обработки форм, я настрою HTML-код с помощью нескольких простых атрибутов и позволю Netlify сделать остальное.
  • Функции Netlify позволяют выполнять действия с данными из моих форм. Я напишу код отправки писем своему сервису email-рассылки и сообщу Netlify, когда необходимо запускать этот код.

Кроме этого я буду управлять списком подписчиков с помощью Buttondown. Это провайдер email-рассылок с простым в использовании API.

Форма

Вот HTML-код формы подписки с некоторыми дополнениями для работы с формами Netlify.

<form class="email-form" name="newsletter" method="POST" data-netlify="true" netlify-honeypot="bot-field">
  <div hidden aria-hidden="true">
    <label>
      Don’t fill this out if you're human: 
      <input name="bot-field" />
    </label>
  </div>
  <label for="email">Your email address</label>
  <div>
    <input type="email" name="email" placeholder="Email" id="email" required />
    <button type="submit">Subscribe</button>
  </div>
</form> 

Я установил для атрибута data-netlify значение true, чтобы привязать Netlify к обработке формы.

Первое поле формы называется bot-field. Я указываю Netlify следить за любыми подозрительными сообщениями, устанавливая атрибут netlify-honeypot в значение bot-field. Затем я скрываю это поле от пользователей с помощью атрибутов html hidden и aria-hidden. Люди не смогут заполнить это ложное поле.

Если форма отправляется с данными в поле bot-field, Netlify узнает, что данные поступают от робота, и игнорирует ввод. Кроме этого Netlify автоматически фильтрует подозрительные сообщения с помощью Askimet.

Следующее поле формы предназначено для ввода email. Я указал тип поля email и что оно обязательно для заполнения.

Форма

Прогрессивные улучшения на JavaScript

По умолчанию Netlify перенаправляет пользователей после заполнения формы на страницу Thank You Page. Но мне это не нужно. Я написал функцию для отправки данных формы без перенаправления.

const processForm = form => {
  const data = new FormData(form)
  data.append('form-name', 'newsletter');
  fetch('/', {
    method: 'POST',
    body: data,
  })
  .then(() => {
    form.innerHTML = `<div class="form--success">Almost there! Check your inbox for a confirmation e-mail.</div>`;
  })
  .catch(error => {
    form.innerHTML = `<div class="form--error">Error: ${error}</div>`;
  })
}

Когда я предоставляю данные формы этой функции через переменную form, она отправляет их с помощью встроенного Fetch API.

Приведенная ниже функция вызывается всякий раз, когда пользователь нажимает кнопку Submit в форме:

const emailForm = document.querySelector('.email-form')
if (emailForm) {
  emailForm.addEventListener('submit', e => {
    e.preventDefault();
    processForm(emailForm);
  })
}

Этот обработчик прогрессивно улучшает поведение формы. Поэтому даже если у пользователя отключен JavaScript, форма все равно будет работать!

Прогрессивные улучшения на JavaScript

Бессерверная функция

Чтобы создать функцию Netlify необходимо выполнить следующие шаги:

  1. Напишите функцию в файле JavaScript.
  2. Сообщите Netlify, где необходимо искать функцию в файле toml проекта.
  3. Добавьте переменные окружения, которые понадобятся. Это можно сделать через интерфейс администратора Netlify. Переменная окружения – это, например, ключ API.

Когда вы запустите свой сайт, функция будет готова к работе.

Функция для моего сайта расположена в папке functions. Поэтому в файле netlify.toml записано следующее:

 [build]
  base = "."
  functions = "./functions"

После этого я добавлю в папку functions файл submission-created.js. Это название даст понять Netlify, что скрипт нужно запускать при отправке данных формы. Полный список событий, который поддерживает сценарий обработчика, указаны в документации Netlify. Если вы правильно настроили свою функцию, то увидите ее название в информационной панели функций Netlify.

Бессерверная функция

Содержимое файла submission-created.js выглядит следующим образом:

require('dotenv').config()
const fetch = require('node-fetch')
const { EMAIL_TOKEN } = process.env
exports.handler = async event => {
  const email = JSON.parse(event.body).payload.email
  console.log(`Recieved a submission: ${email}`)
  return fetch('https://api.buttondown.email/v1/subscribers', {
    method: 'POST',
    headers: {
      Authorization: `Token ${EMAIL_TOKEN}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ email }),
  })
    .then(response => response.json())
    .then(data => {
      console.log(`Submitted to Buttondown:n ${data}`)
    })
    .catch(error => ({ statusCode: 422, body: String(error) }))
}

Разберем приведенный выше код построчно.

Первая строка подключает библиотеку dotenv, которая позволяет использовать переменные окружения. Они используются для хранения конфиденциальной информации. Например, ключей API.

При локальном запуске проекта я устанавливаю переменные окружения в файле .env репозитория. А также проверяю, указан ли он в файле .gitignore. Для развертывания в Netlify я также настроил переменные окружения в веб-интерфейсе Netlify.

Бессерверная функция - 2

Во второй строке я подключаю небольшую библиотеку node-fetch. Это позволяет использовать Javascript Fetch API. С его помощью мы будем отправлять данные в Buttondown. Netlify автоматически включает эту зависимость, если она указана в файле package.json проекта.

В строке 3 я импортирую свой ключ API из объекта переменных окружения process.env.

В четвертой строке объявляется функция. Netlify будем искать ее в переменной export.handler, поэтому мы определяем ее. Единственный параметр, который нам понадобится, – это значение event, которое содержит все данные из формы.

После извлечения адреса электронной почты из события event с помощью JSON.parse я отправляю его в Buttondown. Вот где используется библиотека node-fetch.

Я отправляю запрос POST к https://api.buttondown.email/v1/subscribers, добавляя мой ключ API в заголовок. У API Buttondown немного функций, поэтому вам не понадобится много времени на их изучение.

Тело запроса POST состоит из полученного адреса электронной почты. Затем я получаю ответ от сервера Buttondown, чтобы продиагностировать любые проблемы. Netlify позволяет легко проверять логи созданных функций с помощью console.log!

Развертывание функции

Теперь все готово к работе. Развертывание проходит быстро: настройте интеграцию Netlify с GitHub, и функция запустится после выполнения команды push в вашем проекте.

Проекты Netlify также можно тестировать локально с помощью Netlify Dev. В зависимости от сложности кода локальная разработка может происходить быстрее.

Выполните команду npm i netlify -g, затем команду netlify dev. Netlify Dev будет использовать файл netlify.toml для настройки и запуска проекта локально, включая бессерверные функции.

Предупреждение: Netlify Dev в настоящее время не позволяет запускать бессерверные функции при отправке форм, поэтому вам придется проверить их с помощью предварительных сборок.

Заключение

Мне понадобилось всего 50 строк кода, чтобы создать функциональную форму подписки на email-рассылку.

Я написал весь код с помощью HTML, CSS и JavaScript, не беспокоясь о серверной части. Форма отбраковывает спам, а посетители могут подписаться на рассылку, даже если у них в браузере отключен JavaScript.

Сергей Бензенкоавтор-переводчик статьи «Using Netlify Forms and Netlify Functions to Build an Email Sign-Up Widget»