Пошаговое руководство о том, как использовать Supabase для сохранения и передачи данных от сервера к клиенту в обычном веб-приложении HTML/JavaScript.

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

Моя цель: создать веб-приложение с использованием ванильного HTML и JavaScript и подключить его к серверной части Supabase, чтобы обеспечить постоянство данных приложения, а также обновления в реальном времени, передаваемые в приложение в случае обновлений базы данных. Сначала я создам простое приложение Node, которое подключается, вставляет, запрашивает и подписывается [на уведомления]. Как только я освою это, я создам клиентскую часть, которая делает подобные вещи.

Коллега недавно предупредил меня о Supabase: службе, которая предоставляет серверную часть для веб-приложений с такими возможностями, как управление пользователями и аутентификация, сохранение данных, отправка данных в реальном времени, хранение файлов и бессерверные (пограничные) функции. Сохранность данных обеспечивается управляемой базой данных PostgreSQL. Supabase позволяет нам начать работу на их бесплатном уровне, а также запускать платформу локально — независимо от облачной серверной части. Supabase позиционируется как альтернатива Firebase. Однако я недостаточно хорошо знаю Firebase, чтобы проводить какие-либо сравнения.

Я прочитал несколько статей и просмотрел веб-сайт. Я еще не опробовал Supabase и пока не знаю, с чего начать. Я узнаю достаточно скоро — и поделюсь своей поездкой в ​​​​этой статье.

Надбазовый проект

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

Перейдите на https://app.supabase.com/

Войдите с помощью GitHub. Авторизуйте Supabase на GitHub, когда будет предложено сделать это.

Нажмите «Новый проект».

Укажите имя проекта и установите пароль для доступа к базе данных.

Выберите регион и выберите план (бесплатный может быть хорошим началом).

Нажмите «Создать новый проект».

После создания проекта перейдите в редактор SQL в области базы данных.

Нажмите «Создать таблицу».

Немного отредактируйте предложенное определение таблицы — измените ее имя на app_state.

Нажмите «Выполнить», чтобы создать таблицу в базе данных.

Теперь также создается REST API.

После успешного создания таблицы перейдите на вкладку API. Здесь приведены инструкции по взаимодействию с API, созданным для таблицы.

Теперь бэкэнд создан, пришло время создать приложение для взаимодействия с ним.

Локальная разработка — приложение узла

Чтобы почувствовать взаимодействие с REST API, я сначала создал простое приложение Node, которое использует Supabase JavaScript SDK для взаимодействия с серверной частью. Приложение устанавливает соединение, считывает записи из таблицы APP_STATE и создает новые записи в этой таблице. Во второй итерации я добавлю подписку на изменения в таблице APP_STATE, и о любом изменении сообщается в виде push-уведомления в приложение Node.

Примечание: весь код, показанный в этой статье, доступен в репозитории GitHub: https://github.com/lucasjellema/supabase-lab/tree/main/lab1.

Создайте новую папку в моей локальной среде разработки — lucas-lab. В командной строке выполните:

npm init

Примите все значения по умолчанию в следующем диалоговом окне.

Теперь выполните:

npm install -save @supabase/supabase-js

Создайте файл index.js и скопируйте следующий код:

const { createClient } = require('@supabase/supabase-js')
const supabaseUrl = 'https://bctbnehetetyatkfw.supabase.co'
const supabaseKey = process.env.SUPABASE_KEY
const supabase = createClient(supabaseUrl, supabaseKey)
const main = async () => {
let { data, error } = await supabase
.from('app_state')
.select('name, data')
.range(0,10)
if (error) {
console.error(error)
return
}
console.log(data)
```

Этот код просто запрашивает первые 10 записей из таблицы APP_STATE в бэкенде проекта Supabase и записывает полученные данные в консоль.

Установите переменные среды SUPABASE_KEY и SUPABASE_URL, используя значения, доступные в разделе «Настройки» — «API» — «Ключи API проекта».

export SUPABASE_KEY="<key value>"
export SUPABASE_URL="<url value>"

Или под Windows Powershell:

$Env:SUPABASE_KEY = '<key value>'
$Env:SUPABASE_URL = '<url value>'

(Конечно, для кода, который выполняется только в моей локальной среде, я мог бы также установить значение const supabaseKey и const supabaseUrl непосредственно в исходном коде).

Запустите это приложение с помощью:

node index.js

И вывод, возможно, не впечатляет, но имеет смысл:

Устанавливается соединение с Supabase API и извлекаются данные из таблицы. Просто сейчас не очень.

Затем я добавил запись в таблицу APP_STATE в пользовательском интерфейсе клиента с помощью редактора таблиц.

Я запускаю приложение снова, с немного большим эффектом:

Я добавляю следующий фрагмент в application. Это представляет собой вызов серверной части Supabase для создания новой записи в таблице APP_STATE с именем столбца, установленным как «Новый список», и набором данных для представления JSON объекта со свойством shop.

let { dataI, errorI } = await supabase
.from('app_state')
.insert([
{ name: 'New List', data: {shop:{name:"AH", total:267.12}} }
])

Добавить в качестве первой записи в функции main.

Результат запуска этого кода:

показывает, что из таблицы была извлечена новая запись, которая была сначала добавлена ​​с помощью оператора вставки, который я только что добавил.

Вот редактор таблиц в веб-консоли Supabase (тоже с новой записью):

В режиме реального времени — Push-уведомления от сервера к клиенту об изменениях в таблице

Клиентские приложения могут быть уведомлены Supabase о любых изменениях данных в выбранных таблицах. Нам нужно сделать две вещи, чтобы заставить это работать:

  1. убедиться в том, что в бэкенде Supabase изменения в соответствующих таблицах включены в механизм репликации
  2. подписать функцию в клиентском приложении на соответствующие изменения в назначенной таблице (таблицах)

1. Добавить таблицу в репликацию:

Нажмите на базу данных на боковой панели. Затем при репликации; Репликация скорее всего уже включена. Если это не так, то включите его сейчас. Чтобы добавить таблицу APP_STATE в набор таблиц, изменения которых публикуются, щелкните значок под заголовком *Источник*, который указывает количество таблиц, которые в настоящее время реплицируются.

Выберите таблицу APP_STATE из доступных таблиц.

2. Подпишите клиента на изменения данных в реальном времени.

Подписка приложения на изменения в реальном времени в таблице APP_STATE выполняется с помощью этого фрагмента, где-то в функции main:

subscription1 = supabase
.from('app_state')
.on('UPDATE', (v) => console.log('UPDATE on app_state', v))
.on('INSERT', (v) => console.log('INSERT on app_state', v))
.subscribe((change) => console.log('app_state changed', change))
await sleep(30000)
supabase.removeSubscription(subscription1);

Необходимо добавить функцию sleep() — чтобы приостановить обработку Node-приложения, чтобы дать нам время внести изменения в редакторе таблиц Supabase и увидеть, как эти изменения передаются в клиентское приложение:

function sleep(time) {
  return new Promise(resolve => setTimeout(resolve, time));
}

Запустите приложение узла. Когда он начнется, у вас есть 30 секунд, чтобы внести изменения в данные в таблице APP_STATE через редактор таблиц — и увидеть эффект в консоли.

И вывод из приложения Node:

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

Веб-приложение Vanilla HTML и JavaScript

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

На картинке по-прежнему показан Node — но только для обслуживания статического веб-приложения в браузере (с таким же успехом это может быть nginx или apache httpd). Все взаимодействия с Supabase происходят с клиента — кода JavaScript в браузере.

Я создал файл узла web-server.js. Он делает ровно одно: обслуживает файл index.html в подкаталоге web:

const http = require('http')
const fs = require('fs')
const PORT = 3100
// create an HTTP server that handles HTTP requests; it is handed two parameters: the request and response objects
const server = http.createServer((req, resp) => {
fs.readFile("web/index.html", function (error, page) {
if (error) {
resp.writeHead(404);
resp.write('Contents you are looking are Not Found');
} else {
resp.writeHead(200, { 'Content-Type': 'text/html' });
resp.write(page);
}
resp.end();
})
})
server.listen(PORT);
console.log(`HTTP Server is listening at port ${PORT} for HTTP GET requests`)

Здесь интересен документ index.html. Он показывает содержимое таблицы APP_STATE в браузере:

Краткое руководство по коду:

  1. загрузите Supabase JavaScript Client (SDK) (эта строка аналогична комбинации зависимости @supabase/supabase-js в package.json и require('@supabase/supabase-js') в index.js в приложении узла
  2. Ключ Supabase и URL-адрес не жестко закодированы; вместо этого они изучаются во время выполнения из параметров запроса URL.
  3. когда документ загружается в браузере, эта функция выполняется, и клиент Supabase инициализируется, а затем данные запрашиваются из таблицы APP_STATE.
  4. так же, как и в Node-приложении, вызывается Supabase REST API (через клиентский SDK) для запроса до 10 записей из указанной таблицы APP_STATE
  5. новая строка добавляется в таблицу HTML для каждой записи в данных, полученных из Supabase

Запустите приложение Node web-server.js

http://localhost:3100/?SUPABASE_URL=bctaasdsaqwfw&SUPABASE_KEY=eyJhqams

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

значением параметра запроса SUPABASE_URL является первый сегмент пути в URL-адресе (не включая начальный https:// и общий постфикс .supabase.co).

Браузер открывается — я не утверждал, что это будет красиво — и представляет таблицу, содержащую данные, извлеченные из бэкэнд-таблицы APP_STATE:

Отчет об изменениях в реальном времени в веб-приложении — отправка данных с сервера на клиент в реальном времени

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

Добавьте небольшой фрагмент HTML-кода на страницу index.html прямо под элементом ‹table›:

<h3>Latest Change</h3>
<div id=”breakingNews”></div>
<br /><br />
<button id=”refresh” onclick=”refreshData()”>Refresh</button>

Затем добавьте функцию subscribeAppState в раздел ‹script› в index,html и включите вызов функции внутри функции, зарегистрированной для события DOMContentLoaded:

function subscribeAppState() {
subscription1 = supabaseClient
.from('app_state')
.on('UPDATE', (v) => { console.log('UPDATE on app_state', v); reportDataChange(v) })
.on('INSERT', (v) => { console.log('INSERT on app_state', v); reportDataChange(v) })
.on('DELETE', (v) => { console.log('DELETE on app_state', v); reportDataChange(v) })
.subscribe((change) => console.log('app_state changed', change))
}

Сохраните файл index.html. Обновите браузер.

Таблица по-прежнему отображается вместе с заголовком Последнее изменение и кнопкой Обновить. Консоль показывает сообщение о том, что подписка состоялась.

Если я сейчас внесу изменения в табличный редактор Supabase — например удалю запись:

то об этом изменении почти сразу же сообщается в браузере.

После нажатия кнопки обновить таблица также обновляется, чтобы отразить текущую ситуацию в таблице APP_STATE.

Запуск веб-приложения на страницах GitHub

Веб-приложение теперь работает локально на моем ноутбуке с помощью приложения веб-сервера Node. Это работает, но не является желаемой ситуацией. В идеале мне не нужно ничего запускать, чтобы получить доступ к приложению и особенно для того, чтобы вы могли получить доступ к моему приложению. Конечно, в этом случае мне нужно будет передать ключ Supabase и URL-адрес, чтобы приложение можно было использовать для вас — но, возможно, я сделаю именно это. Итак, как я могу сделать это статическое веб-приложение (одноразовая загрузка статических неизменяемых веб-ресурсов в браузер — это все, что требуется для запуска приложения) доступным для всех?

Вот где GitHub Pages приходит на помощь. GitHub Pages предназначен для размещения ваших личных страниц, страниц организации или проектов из репозитория GitHub. Это все, что мне нужно, чтобы сделать приложение доступным.

Для этого я зайду в консоль репозитория GitHub и включу GitHub Pages, указав ветку и каталог, в котором находятся публикуемые ресурсы:

После сохранения этих изменений появится следующее сообщение:

Публикация может занять несколько минут. Когда это произойдет, я — и вы тоже — сможете получить доступ к приложению по адресу: https://lucasjellema.github.io/supabase-lab/lab1/web/index.html. Конечно, необходимо добавить параметры запроса SUPABASE_KEY и SUPABASE_URL.

Ресурсы

весь код, показанный в этой статье, доступен в репозитории GitHub: https://github.com/lucasjellema/supabase-lab/tree/main/lab1.

Клиентская библиотека Supabase JS — https://supabase.com/docs/reference/javascript/supabase-client и https://github.com/supabase/supabase-js и (команды, связанные с базой данных) https:/ /supabase.com/docs/reference/javascript/insert

Прочитайте описание того, как включить публикацию изменений в реальном времени для таблиц: https://supabase.com/docs/guides/database/replication

Первоначально опубликовано на https://technology.amis.nl 5 июня 2022 г.

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter и LinkedIn. Посетите наш Community Discord и присоединитесь к нашему Коллективу талантов.