Добавление динамических и асинхронных функций на сайты JAMstack

Опубликовано: 2022-03-10
Краткое резюме ↬ Пропуск серверов и использование JAMstack для создания и доставки веб-сайтов и приложений может сэкономить время, деньги и головную боль, позволяя нам предоставлять только статические ресурсы в CDN. Но отказ от традиционных серверных развертываний означает, что стандартные подходы к динамическим асинхронным взаимодействиям на наших сайтах и ​​в приложениях больше недоступны.

Означает ли это, что сайты JAMstack не могут обрабатывать динамические взаимодействия? Точно нет!

Сайты JAMstack отлично подходят для создания высокодинамичных асинхронных взаимодействий. С некоторыми небольшими изменениями в том, как мы думаем о нашем коде, мы можем создавать забавные, захватывающие взаимодействия, используя только статические ресурсы!

Все чаще можно увидеть веб-сайты, созданные с использованием JAMstack, то есть веб-сайты, которые можно использовать в виде статических HTML-файлов, созданных с помощью JavaScript, разметки и API. Компании любят JAMstack, потому что он снижает затраты на инфраструктуру, ускоряет доставку и снижает барьеры для повышения производительности и безопасности, поскольку доставка статических ресурсов устраняет необходимость масштабирования серверов или обеспечения высокой доступности баз данных (что также означает отсутствие серверов или баз данных, которые могут быть взломан). Разработчикам нравится JAMstack, потому что он упрощает запуск веб-сайта в Интернете: нет серверов для управления или развертывания; мы можем написать интерфейсный код, и он просто заработает , как по волшебству .

(«Магия» в данном случае — это автоматизированное статическое развертывание, которое можно бесплатно получить в ряде компаний, в том числе в Netlify, где я работаю.)

Но если вы потратите много времени на разговоры с разработчиками о JAMstack, возникнет вопрос, может ли JAMstack работать с серьезными веб-приложениями. В конце концов, сайты JAMstack — это статические сайты, верно? И разве статические сайты не слишком ограничены в своих возможностях?

Это очень распространенное заблуждение, и в этой статье мы собираемся разобраться, откуда оно взялось, рассмотрим возможности JAMstack и рассмотрим несколько примеров использования JAMstack для создания серьезных веб-приложений.

Основы JAMstack

Фил Хоксворт объясняет, что на самом деле означает JAMStack и когда имеет смысл использовать его в ваших проектах, а также как это влияет на инструменты и интерфейсную архитектуру. Читать статью по теме →

Еще после прыжка! Продолжить чтение ниже ↓

Что делает сайт JAMstack «статичным»?

Веб-браузеры сегодня загружают файлы HTML, CSS и JavaScript, как и в 90-х годах.

Сайт JAMstack по своей сути представляет собой папку с файлами HTML, CSS и JavaScript.

Это «статические активы», что означает, что нам не нужен промежуточный шаг для их создания (например, проектам PHP, таким как WordPress, нужен сервер для генерации HTML при каждом запросе).

В этом истинная сила JAMstack: для его работы не требуется никакой специализированной инфраструктуры. Вы можете запустить сайт JAMstack на своем локальном компьютере, поместив его в предпочитаемую сеть доставки контента (CDN), разместив его с помощью таких сервисов, как GitHub Pages — вы даже можете перетащить папку в свой любимый FTP-клиент, чтобы загрузить ее. на виртуальный хостинг.

Статические активы не обязательно означают статический опыт

Поскольку сайты JAMstack состоят из статических файлов, легко предположить, что работа на этих сайтах, знаете ли, статична . Но это не так!

JavaScript способен делать множество динамических вещей. В конце концов, современные фреймворки JavaScript представляют собой статические файлы после того, как мы пройдем этап сборки, и существуют сотни примеров невероятно динамичного веб-сайта, основанного на них.

Существует распространенное заблуждение, что «статический» означает негибкий или фиксированный. Но все, что на самом деле означает «статический» в контексте «статических сайтов», заключается в том, что браузерам не нужна никакая помощь в доставке их контента — они могут использовать их изначально, без того, чтобы сервер выполнял предварительный этап обработки.

Или, по-другому:

«Статические активы» не означают статические приложения; это означает, что сервер не требуется.

Может ли JAMstack сделать это?

Если кто-то спрашивает о создании нового приложения, обычно можно увидеть предложения по подходам JAMstack, таким как Gatsby, Eleventy, Nuxt и другим подобным инструментам. Столь же часто возникают возражения: «генераторы статических сайтов не могут _______», где _______ — это что-то динамическое.

Но, как мы уже упоминали в предыдущем разделе, сайты JAMstack могут обрабатывать динамический контент и взаимодействия!

Вот неполный список вещей, которые, как я неоднократно слышал, люди утверждают, что JAMstack не может справиться, что он определенно может:

  • Загружать данные асинхронно
  • Обрабатывать файлы обработки, например манипулировать изображениями
  • Чтение и запись в базу данных
  • Обработка аутентификации пользователя и защита контента за логином

В следующих разделах мы рассмотрим, как реализовать каждый из этих рабочих процессов на сайте JAMstack.

Если вам не терпится увидеть динамический JAMstack в действии, вы можете сначала проверить демоверсии, а затем вернуться и узнать, как они работают.

Примечание о демо :

Эти демки написаны без каких-либо фреймворков. Это только HTML, CSS и стандартный JavaScript. Они были созданы с учетом современных браузеров (например, Chrome, Firefox, Safari, Edge) и используют преимущества новых функций, таких как модули JavaScript, шаблоны HTML и Fetch API. Полифилы не добавлялись, поэтому, если вы используете неподдерживаемый браузер, демонстрация, скорее всего, не удастся.

Асинхронно загружать данные из стороннего API

«Что, если мне нужно получить новые данные после создания моих статических файлов?»

В JAMstack мы можем воспользоваться многочисленными библиотеками асинхронных запросов, включая встроенный API Fetch, для загрузки данных с помощью JavaScript в любой момент.

Демонстрация: поиск стороннего API на сайте JAMstack

Обычный сценарий, требующий асинхронной загрузки, — это когда нужный нам контент зависит от пользовательского ввода. Например, если мы создаем страницу поиска для Rick & Morty API , мы не знаем, какой контент отображать, пока кто-то не введет поисковый запрос.

Чтобы справиться с этим, нам нужно:

  1. Создайте форму, в которой люди могут ввести свой поисковый запрос,
  2. Слушайте отправку формы,
  3. Получить условие поиска из отправки формы,
  4. Отправьте асинхронный запрос к Rick & Morty API, используя поисковый запрос,
  5. Отображение результатов запроса на странице.

Во-первых, нам нужно создать форму и пустой элемент, который будет содержать наши результаты поиска, который выглядит так:

 <form> <label for="name">Find characters by name</label> <input type="text" name="name" required /> <button type="submit">Search</button> </form> <ul></ul>

Далее нам нужно написать функцию, которая обрабатывает отправку форм. Эта функция будет:

  • Запретить отправку формы по умолчанию
  • Получить поисковый запрос из ввода формы
  • Используйте Fetch API, чтобы отправить запрос в Rick & Morty API, используя поисковый запрос.
  • Вызов вспомогательной функции, отображающей результаты поиска на странице.

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

Вот как этот код выглядит в целом:

 <script type="module"> import showResults from './show-results.js'; const form = document.querySelector('form'); const handleSubmit = async event => { event.preventDefault(); // get the search term from the form input const name = form.elements['name'].value; // send a request to the Rick & Morty API based on the user input const characters = await fetch( `https://rickandmortyapi.com/api/character/?name=${name}`, ) .then(response => response.json()) .catch(error => console.error(error)); // add the search results to the DOM showResults(characters.results); }; form.addEventListener('submit', handleSubmit); </script>

Примечание: чтобы сосредоточиться на динамическом поведении JAMstack, мы не будем обсуждать, как пишутся служебные функции, такие как showResults. Однако код тщательно прокомментирован, поэтому ознакомьтесь с исходным кодом, чтобы узнать, как он работает!

Имея этот код, мы можем загрузить наш сайт в браузере и увидеть пустую форму без каких-либо результатов:

Пустая форма поиска
Пустая форма поиска (большой превью)

Если мы введем имя персонажа (например, «rick») и нажмем «search», мы увидим список персонажей, имена которых содержат «rick»:

Форма поиска заполнена словом «rick», а символы с именем «Rick» отображаются ниже.
Мы видим результаты поиска после заполнения формы. (Большой превью)

Привет! Этот статический сайт просто динамически загружал данные? Святые ведра!

Вы можете сами попробовать это в демо-версии или ознакомиться с полным исходным кодом для получения более подробной информации.

Выполняйте дорогостоящие вычислительные задачи с устройства пользователя

Во многих приложениях нам нужно делать довольно ресурсоемкие вещи, например, обрабатывать изображение. Хотя некоторые из этих видов операций возможны только с использованием клиентского JavaScript, не обязательно заставлять устройства ваших пользователей выполнять всю эту работу. Если они используют устройство с низким энергопотреблением или пытаются растянуть последние 5% времени автономной работы, заставлять свое устройство выполнять кучу работы, вероятно, будет для них разочаровывающим опытом.

Значит ли это, что приложениям JAMstack не повезло? Нисколько!

«А» в JAMstack означает API. Это означает, что мы можем отправить эту работу в API и избежать раскручивания компьютерных вентиляторов наших пользователей до настройки «зависания».

«Но подождите», — можете сказать вы. «Если нашему приложению нужно выполнять нестандартную работу, и для этой работы требуется API, разве это не означает, что мы просто создаем сервер?»

Благодаря мощности бессерверных функций нам это не нужно!

Бессерверные функции (также называемые «лямбда-функциями») — это своего рода API, не требующий какого-либо шаблонного кода сервера. Мы можем написать старую простую функцию JavaScript, и вся работа по развертыванию, масштабированию, маршрутизации и т. д. перекладывается на нашего бессерверного провайдера по выбору.

Использование бессерверных функций не означает отсутствия сервера; это просто означает, что нам не нужно думать о сервере.

Бессерверные функции — это арахисовое масло для нашего JAMstack: они открывают целый мир мощной динамической функциональности, даже не требуя от нас работы с серверным кодом или devops.

Демонстрация: преобразование изображения в оттенки серого

Предположим, у нас есть приложение, которому необходимо:

  • Скачать изображение с URL-адреса
  • Преобразуйте это изображение в оттенки серого
  • Загрузите преобразованное изображение в репозиторий GitHub.

Насколько я знаю, нет никакого способа сделать подобное преобразование изображений полностью в браузере — и даже если бы он был, это довольно ресурсоемкая вещь, поэтому мы, вероятно, не хотим возлагать такую ​​нагрузку на наших пользователей. устройства.

Вместо этого мы можем отправить URL-адрес для преобразования в бессерверную функцию, которая сделает за нас тяжелую работу и отправит обратно URL-адрес преобразованного изображения.

Для нашей бессерверной функции мы будем использовать функции Netlify. В код нашего сайта мы добавляем папку на корневом уровне под названием «функции» и создаем внутри новый файл с именем «convert-image.js». Затем мы пишем то, что называется обработчиком, который получает и, как вы уже догадались, обрабатывает запросы к нашей бессерверной функции.

Чтобы преобразовать изображение, это выглядит так:

 exports.handler = async event => { // only try to handle POST requests if (event.httpMethod !== 'POST') { return { statusCode: 404, body: '404 Not Found' }; } try { // get the image URL from the POST submission const { imageURL } = JSON.parse(event.body); // use a temporary directory to avoid intermediate file cruft // see https://www.npmjs.com/package/tmp const tmpDir = tmp.dirSync(); const convertedPath = await convertToGrayscale(imageURL, tmpDir); // upload the processed image to GitHub const response = await uploadToGitHub(convertedPath, tmpDir.name); return { statusCode: 200, body: JSON.stringify({ url: response.data.content.download_url, }), }; } catch (error) { return { statusCode: 500, body: JSON.stringify(error.message), }; } };

Эта функция делает следующее:

  1. Проверяет, был ли запрос отправлен с использованием метода HTTP POST.
  2. Захватывает URL-адрес изображения из тела POST
  3. Создает временный каталог для хранения файлов, которые будут очищены после завершения выполнения функции.
  4. Вызывает вспомогательную функцию, которая преобразует изображение в оттенки серого.
  5. Вызывает вспомогательную функцию, которая загружает преобразованное изображение на GitHub.
  6. Возвращает объект ответа с кодом состояния HTTP 200 и URL-адресом недавно загруженного изображения.

Примечание . Мы не будем рассказывать, как работают вспомогательные функции для преобразования изображений или загрузки на GitHub, но исходный код хорошо прокомментирован, чтобы вы могли увидеть, как это работает.

Затем нам нужно добавить форму, которая будет использоваться для отправки URL-адресов для обработки, и место для отображения до и после:

 <form action="/.netlify/functions/convert-image" method="POST" > <label for="imageURL">URL of an image to convert</label> <input type="url" name="imageURL" required /> <button type="submit">Convert</button> </form> <div></div>

Наконец, нам нужно добавить прослушиватель событий в форму, чтобы мы могли отправлять URL-адреса нашей бессерверной функции для обработки:

 <script type="module"> import showResults from './show-results.js'; const form = document.querySelector('form'); form.addEventListener('submit', event => { event.preventDefault(); // get the image URL from the form const imageURL = form.elements['imageURL'].value; // send the image off for processing const promise = fetch('/.netlify/functions/convert-image', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ imageURL }), }) .then(result => result.json()) .catch(error => console.error(error)); // do the work to show the result on the page showResults(imageURL, promise); }); </script>

После развертывания сайта (вместе с его новой папкой «функции») в Netlify и/или запуска Netlify Dev в нашем CLI мы можем увидеть форму в нашем браузере:

Пустая форма преобразования изображения
Пустая форма, которая принимает URL-адрес изображения (большой предварительный просмотр)

Если мы добавим URL-адрес изображения в форму и нажмем «конвертировать», мы увидим «обработка…» на мгновение, пока происходит преобразование, затем мы увидим исходное изображение и его недавно созданный аналог в градациях серого:

Форма, заполненная URL-адресом изображения, показывающая исходное изображение слева внизу и преобразованное изображение справа.
Изображение преобразуется из полноцветного в оттенки серого. (Большой превью)

О черт! Наш сайт JAMstack только что занимался довольно серьезным делом, и нам не нужно было думать о серверах или разряжать батареи наших пользователей!

Используйте базу данных для хранения и извлечения записей

Во многих приложениях нам неизбежно понадобится возможность сохранять пользовательский ввод. А это значит, что нам нужна база данных.

Вы можете подумать: «Так вот оно что, верно? Джиг встал? Конечно, сайт JAMstack, который, как вы нам сказали, представляет собой просто набор файлов в папке, нельзя подключить к базе данных!»

О наоборот.

Как мы видели в предыдущем разделе, бессерверные функции дают нам возможность делать всевозможные мощные вещи без необходимости создавать собственные серверы.

Точно так же мы можем использовать инструменты «база данных как услуга» (DBaaS) (такие как Fauna) для чтения и записи в базу данных без необходимости настраивать или размещать ее самостоятельно.

Инструменты DBaaS значительно упрощают процесс настройки баз данных для веб-сайтов: создать новую базу данных так же просто, как определить типы данных, которые мы хотим хранить. Инструменты автоматически генерируют весь код для управления операциями создания, чтения, обновления и удаления (CRUD) и делают его доступным для использования через API, поэтому нам не нужно фактически управлять базой данных; мы просто получаем, чтобы использовать его.

Демонстрация: создание страницы петиции

Если мы хотим создать небольшое приложение для сбора цифровых подписей для петиции, нам нужно настроить базу данных для хранения этих подписей и позволить странице считывать их для отображения.

В этой демонстрации мы будем использовать Fauna в качестве поставщика DBaaS. Мы не будем углубляться в то, как работает Fauna, но в интересах демонстрации небольших усилий, необходимых для настройки базы данных, давайте перечислим каждый шаг и щелкнем, чтобы получить готовую к использованию базу данных:

  1. Создайте учетную запись фауны на https://fauna.com
  2. Нажмите «создать новую базу данных»
  3. Дайте базе данных имя (например, «dynamic-jamstack-demos»)
  4. Нажмите «создать»
  5. Нажмите «Безопасность» в левом меню на следующей странице.
  6. Нажмите «новый ключ»
  7. Измените раскрывающийся список ролей на «Сервер».
  8. Добавьте имя для ключа (например, «Dynamic JAMstack Demos»)
  9. Храните ключ в безопасном месте для использования с приложением.
  10. Нажмите «сохранить»
  11. Нажмите «GraphQL» в меню слева.
  12. Нажмите «импортировать схему»
  13. Загрузите файл с именем db-schema.gql , содержащий следующий код:
 type Signature { name: String! } type Query { signatures: [Signature!]! }

Как только мы загрузим схему, наша база данных будет готова к использованию. (Серьезно.)

Тринадцать шагов — это много, но с этими тринадцатью шагами мы только что получили базу данных, GraphQL API, автоматическое управление емкостью, масштабированием, развертыванием, безопасностью и т. д. — всем этим занимаются специалисты по базам данных. Бесплатно. Какое время быть живым!

Чтобы попробовать это, опция «GraphQL» в левом меню дает нам проводник GraphQL с документацией по доступным запросам и мутациям, которые позволяют нам выполнять операции CRUD.

Примечание . В этом посте мы не будем вдаваться в подробности о запросах и мутациях GraphQL, но Ева Порчелло написала отличное введение в отправку запросов и мутаций GraphQL, если вы хотите ознакомиться с тем, как это работает.

Когда база данных готова к работе, мы можем создать бессерверную функцию, которая будет хранить новые подписи в базе данных:

 const qs = require('querystring'); const graphql = require('./util/graphql'); exports.handler = async event => { try { // get the signature from the POST data const { signature } = qs.parse(event.body); const ADD_SIGNATURE = ` mutation($signature: String!) { createSignature(data: { name: $signature }) { _id } } `; // store the signature in the database await graphql(ADD_SIGNATURE, { signature }); // send people back to the petition page return { statusCode: 302, headers: { Location: '/03-store-data/', }, // body is unused in 3xx codes, but required in all function responses body: 'redirecting...', }; } catch (error) { return { statusCode: 500, body: JSON.stringify(error.message), }; } };

Эта функция делает следующее:

  1. Захватывает значение подписи из данных формы POST
  2. Вызывает вспомогательную функцию, которая сохраняет подпись в базе данных
  3. Определяет мутацию GraphQL для записи в базу данных
  4. Отправляет мутацию с помощью вспомогательной функции GraphQL.
  5. Перенаправляет обратно на страницу, которая отправила данные

Затем нам нужна бессерверная функция для считывания всех подписей из базы данных, чтобы мы могли показать, сколько людей поддержало нашу петицию:

 const graphql = require('./util/graphql'); exports.handler = async () => { const { signatures } = await graphql(` query { signatures { data { name } } } `); return { statusCode: 200, body: JSON.stringify(signatures.data), }; };

Эта функция отправляет запрос и возвращает его.

Важное примечание о конфиденциальных ключах и приложениях JAMstack :

В этом приложении следует отметить, что мы используем бессерверные функции для выполнения этих вызовов, потому что нам нужно передать секретный ключ сервера в Fauna, который доказывает, что у нас есть доступ для чтения и записи к этой базе данных. Мы не можем поместить этот ключ в клиентский код, потому что это означало бы, что любой мог бы найти его в исходном коде и использовать для выполнения операций CRUD в нашей базе данных. Бессерверные функции имеют решающее значение для обеспечения конфиденциальности закрытых ключей в приложениях JAMstack.

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

 <form action="/.netlify/functions/add-signature" method="POST"> <label for="signature">Your name</label> <input type="text" name="signature" required /> <button type="submit">Sign</button> </form> <ul class="signatures"></ul> <script> fetch('/.netlify/functions/get-signatures') .then(res => res.json()) .then(names => { const signatures = document.querySelector('.signatures'); names.forEach(({ name }) => { const li = document.createElement('li'); li.innerText = name; signatures.appendChild(li); }); }); </script>

Если мы загрузим это в браузере, мы увидим нашу форму петиции с подписями под ней:

Пустая форма петиции со списком подписей ниже
Пустая форма, которая принимает цифровую подпись (большой предварительный просмотр)

Затем, если мы добавим нашу подпись…

Форма петиции с именем в поле, но еще не отправленным
Форма петиции с заполненным именем (большой предварительный просмотр)

… и отправьте его, мы увидим, что наше имя добавлено в конец списка:

Пустая форма петиции с новой подписью внизу списка
Форма петиции очищается, и новая подпись добавляется в конец списка. (Большой превью)

Горячая собачка! Мы только что написали полноценное приложение JAMstack на основе базы данных, содержащее около 75 строк кода и 7 строк схемы базы данных!

Защитите контент с помощью аутентификации пользователя

«Ладно, на этот раз вы наверняка застряли», — можете подумать вы. «Сайт JAMstack никак не может обрабатывать аутентификацию пользователей. Как, черт возьми, это вообще сработает?!

Я расскажу тебе, друг мой, как это работает: с нашими проверенными бессерверными функциями и OAuth.

OAuth – это широко распространенный стандарт, позволяющий людям предоставлять приложениям ограниченный доступ к данным своей учетной записи, а не делиться своими паролями. Если вы когда-либо входили в службу с помощью другой службы (например, «войдите с помощью своей учетной записи Google»), вы использовали OAuth раньше.

Примечание. Мы не будем углубляться в то, как работает OAuth, но Аарон Парецки написал подробный обзор OAuth, в котором описаны детали и рабочий процесс.

В приложениях JAMstack мы можем использовать преимущества OAuth и веб-токенов JSON (JWT), которые он предоставляет нам для идентификации пользователей, защиты контента и разрешения его просмотра только вошедшим в систему пользователям.

Демонстрация: требуется вход для просмотра защищенного контента

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

  1. Поставщик удостоверений, который управляет пользователями и процессом входа.
  2. Элементы пользовательского интерфейса для управления входом и выходом из системы
  3. Бессерверная функция, которая проверяет наличие вошедшего в систему пользователя с помощью JWT и возвращает защищенный контент, если он предоставлен.

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

Чтобы включить его:

  • Посетите панель управления Netlify
  • Выберите сайт, для которого требуется авторизация, из списка ваших сайтов.
  • Нажмите «личность» в верхней панели навигации.
  • Нажмите кнопку «Включить идентификацию».

Мы можем добавить Netlify Identity на наш сайт, добавив разметку, показывающую контент, вышедший из системы, и добавив элемент для отображения защищенного контента после входа в систему:

 <div class="content logged-out"> <h1>Super Secret Stuff!</h1> <p> only my bestest friends can see this content</p> <button class="login">log in / sign up to be my best friend</button> </div> <div class="content logged-in"> <div class="secret-stuff"></div> <button class="logout">log out</button> </div>

Эта разметка использует CSS для отображения содержимого в зависимости от того, вошел ли пользователь в систему или нет. Однако мы не можем полагаться на это для реальной защиты контента — любой может просмотреть исходный код и украсть наши секреты!

Вместо этого мы создали пустой div, который будет содержать наш защищенный контент, но нам нужно будет сделать запрос к бессерверной функции, чтобы фактически получить этот контент. Вскоре мы рассмотрим, как это работает.

Затем нам нужно добавить код, чтобы наша кнопка входа работала, загружала защищенный контент и отображала его на экране:

 <script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script> <script> const login = document.querySelector('.login'); login.addEventListener('click', () => { netlifyIdentity.open(); }); const logout = document.querySelector('.logout'); logout.addEventListener('click', () => { netlifyIdentity.logout(); }); netlifyIdentity.on('logout', () => { document.querySelector('body').classList.remove('authenticated'); }); netlifyIdentity.on('login', async () => { document.querySelector('body').classList.add('authenticated'); const token = await netlifyIdentity.currentUser().jwt(); const response = await fetch('/.netlify/functions/get-secret-content', { headers: { Authorization: `Bearer ${token}`, }, }).then(res => res.text()); document.querySelector('.secret-stuff').innerHTML = response; }); </script>

Вот что делает этот код:

  1. Загружает виджет Netlify Identity, который представляет собой вспомогательную библиотеку, которая создает модальное окно входа в систему, обрабатывает рабочий процесс OAuth с помощью Netlify Identity и предоставляет нашему приложению доступ к информации о вошедшем в систему пользователе.
  2. Добавляет прослушиватель событий к кнопке входа в систему, который запускает модальное окно входа в систему Netlify Identity для открытия.
  3. Добавляет прослушиватель событий к кнопке выхода, который вызывает метод выхода Netlify Identity.
  4. Добавляет обработчик событий для выхода из системы, чтобы удалить аутентифицированный класс при выходе из системы, который скрывает содержимое входа в систему и показывает содержимое выхода из системы.
  5. Добавляет обработчик событий для входа в систему, который:
    1. Добавляет аутентифицированный класс, чтобы показать содержимое входа и скрыть содержимое выхода.
    2. Захватывает JWT вошедшего в систему пользователя
    3. Вызывает бессерверную функцию для загрузки защищенного контента, отправляя JWT в заголовке авторизации.
    4. Помещает секретный контент в div secret-stuff, чтобы зарегистрированные пользователи могли его видеть.

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

 exports.handler = async (_event, context) => { try { const { user } = context.clientContext; if (!user) throw new Error('Not Authorized'); return { statusCode: 200, headers: { 'Content-Type': 'text/html', }, body: `

Вы приглашены, ${user.user_metadata.full_name}!

Если ты можешь это прочитать, значит, мы лучшие друзья.

Вот секреты моей вечеринки по случаю дня рождения:
jason.af/вечеринка

`, }; } поймать (ошибка) { вернуть { код состояния: 401, тело: «Не авторизовано», }; } };

Эта функция делает следующее:

  1. Проверяет наличие пользователя в аргументе контекста бессерверной функции.
  2. Выдает ошибку, если пользователь не найден
  3. Возвращает секретный контент после проверки того, что вошедший в систему пользователь запросил его

Функции Netlify обнаружат JWT Netlify Identity в заголовках авторизации и автоматически поместят эту информацию в контекст — это означает, что мы можем проверить действительные JWT без необходимости писать код для проверки JWT!

Когда мы загружаем эту страницу в наш браузер, мы сначала увидим страницу выхода из системы:

Представление «Выход из системы», показывающее информацию о входе в систему или создании учетной записи
При выходе из системы мы можем видеть только информацию о входе в систему. (Большой предварительный просмотр)

Если мы нажмем кнопку для входа, мы увидим виджет Netlify Identity:

Модальное окно, показывающее вкладки регистрации и входа с отображенной формой входа
Виджет Netlify Identity Widget предоставляет все возможности входа/регистрации. (Большой превью)

После авторизации (или регистрации) мы можем увидеть защищенный контент:

Вход в систему с отображением информации о вечеринке по случаю дня рождения
После входа в систему мы можем увидеть защищенный контент. (Большой превью)

Вау! Мы только что добавили логин пользователя и защищенный контент в приложение JAMstack!

Что делать дальше

JAMstack — это гораздо больше, чем «просто статические сайты» — мы можем реагировать на взаимодействие с пользователем, хранить данные, выполнять аутентификацию пользователей и практически все, что мы хотим делать на современном веб-сайте. И все это без необходимости предоставления, настройки или развертывания сервера!

Что вы хотите построить с помощью JAMstack? Есть ли что-то, с чем вы все еще не уверены, что JAMstack справится? Я хотел бы услышать об этом — напишите мне в Твиттере или в комментариях!