Blazor та Heroku: як безкоштовно створити інтерактивний додаток

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Мене звати Віталій Дацишин, я працюю .NET розробником в компанії Intellias. В цій статті я поділюсь своїм досвідом створення сайту з Blazor та його розгортання з Heroku.

Цей проект є моїм pet project’ом, тому було всього дві вимоги: спробувати щось нове та зробити все максимально дешево (в ідеалі, безкоштовно). Технології, які я використав, відповідають цим вимогам — це Blazor, SQLite і Heroku.

Blazor

Blazor — це UI-фреймворк для створення інтерактивних додатків, які можуть працювати на платформі .NET як на стороні сервера, так і на стороні клієнта. Blazor є відносно молодим фреймворком, перший реліз був у 2018, тому він зазнав значного впливу сучасних фреймворків-гігантів для створення клієнтських додатків — Angular, React, VueJS. Головною перевагою для розробників є використання C# замість JavaScript і можливість використання екосистеми .NET з усіма її бібліотеками.

Є дві моделі розгортання (hosting) — Server і WebAssembly.

WebAssembly

При цьому способі хостингу компоненти Blazor запускаються у браузері, який використовує середовище виконання .NET на базі WebAssembly на стороні клієнта. .NET runtime завантажується разом із додатком Blazor WebAssembly та це дозволяє запускати звичайний код .NET безпосередньо у браузері. Ніяких плагінів або перетворювачів коду не потрібно. Blazor WebAssembly працює з усіма сучасними веббраузерами — як десктопними, так і мобільними. Ці додатки можуть бути розгорнуті як повністю автономні статичні сайти взагалі без будь-якого компонента сервера .NET. Або їх можна поєднати з ASP.NET Core, щоб забезпечити повну веброзробку з .NET, де код можна легко поділити між клієнтом і сервером.

Server

При цьому способі хостингу компоненти Blazor запускаються на сервері як додаток ASP.NET Core. Всі взаємодії та оновлення інтерфейсу обробляються через з’єднання SignalR.

Власне, саме цей спосіб хостингу я і обрав, тому що:

  • з ним швидко і просто розпочати розробку;
  • все в одному проєкті — дешевше і легше зібрати його в один docker image;
  • всі завантажені файли на клієнт мають набагато менший розмір порівняно з Blazor WebAssembly;
  • можливий доступ до захищених ресурсів, таких як бази даних або хмарні сервіси.

Серед негативних моментів варто виділити, що буде додаткова затримка через надсилання даних туди і назад. Це може бути особливо критичним при слабкому інтернеті.

Компоненти

Ключовим елементом додатків на Blazor є компоненти. Хто працював з фреймворками клієнтської сторони, такими як Angular, React, VueJS, той стикався з компонентами, які, по суті, структурують додаток. У Blazor застосовується схожа концепція.

Клас компонента зазвичай записується у вигляді сторінки розмітки Razor із розширенням файлу .razor. Синтаксис Razor поєднує розмітку HTML із кодом C#. Замість того, щоб працювати з JavaScript, jQuery чи іншим фреймворком для викликів API, у розділі @code можна реалізувати методи життєвого циклу компонентів та методи компонентів. Компоненти можна повторно використовувати в інших проєктах і переносити у вигляді бібліотеки класів Razor.

Приклад

@page "/news"

@inject TopFighterDbContext DbContext

@foreach (var news in DbContext.News)
{
   <div class="row">
       <div class="col-md-6">
           <ImageCarousel ImageNames="@news.ImageNames"/>
       </div>
       <div class="col-md-6">
           <h1>@news.Caption</h1>
           <p>@news.Description</p>
       </div>
   </div>
   <hr>
}

SQLite

Дійшовши до вибору бази даних, я згадав про початкові вимоги — щось нове і дешеве. В цих пошуках я знайшов реляційну систему керування базами даних — SQLite. Найважливішим фактором для мене було те, що вся база даних — це, по суті, один файл (file based). Крім того, формат файлу є міжплатформеним. Базу даних, створену на одній машині, можна скопіювати та використовувати на іншій машині з іншою архітектурою. Для мене це було важливо, адже мені не потрібен буде окремий ресурс в хмарному середовищі для БД, а все буде разом. Економія — моє все.

Також, це одна з найпоширеніших баз даних, тому було дуже легко інтегруватися з нею в моєму додатку.

services.AddDbContext(options =>
   options.UseSqlite(_configuration.GetConnectionString("TopFighterDb")));

Тут connection string це шлях до файлу.

"ConnectionStrings": {
 "TopFighterDb": "Data Source=TopFighter.db"
}

Так як це є реляційна БД і використовується Entity Framework Core, то і міграції тут підійдуть.

Heroku

Heroku — це хмарна, повністю керована платформа як послуга (PaaS) для створення, запуску та управління програмами. З коробки Heroku підтримує багато різних мов програмування, але не підтримує .NET. Проте завжди є Docker.

Dyno — це linux контейнер, в якому виконуються всі програми, які розгорнуті в Heroku.

Я розглядав тільки безкоштовні dyno, і вони є досить непоганими та повністю задовольняють мої потреби. Серед переваг безкоштовного плану також є можливість додати своє доменне ім’я сайту.

В безкоштовному плані дається 1000 годин роботи dyno на місяць (550 годин одразу + 450 за прив’язку картки). Для мого одного додатку цього вистачає: 31 день * 24 години у добі = 744 години в місяць. Щодо негативної сторони, то це те, що через 30 хвилин неактивності dyno засинає, і це критично для мене, бо:

  • усе, що було додано в БД (нагадую, що це просто файл) протягом роботи dyno зникає, адже коли dyno засинає, всі дані програми стираються, а коли dyno прокидається, все відновлюється з моменту останнього деплою;
  • запит до сплячого dyno буде оброблятись дуже довго.

Як розв’язати цю проблему? Не дати dyno заснути. Для цього я використав крон джобу (заплановане виконання вебсайтів та скриптів), яку налаштував на виклик мого сайту кожні 30 хвилин. Таким чином dyno ніколи не засинає.

Розгортання сайту

1. Спершу потрібно створити акаунт в Heroku.

2. Далі в проєкт потрібно додати Dockerfile.

FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build-env
WORKDIR /app
COPY *\.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/sdk:3.1
WORKDIR /app
COPY --from=build-env /app/out .

CMD dotnet TopFighter.dll

3. В терміналі вводимо команду heroku login, яка відкриє в браузері сторінку з формою для логіну.

4. Після успішного логіну створюємо додаток в Heroku.

Тут вже є посилання на додаток і виділений гіт, куди потрібно запушити код.

5. Та перед цим, потрібно сказати heroku, що додаток потрібно збирати як контейнер, тому що heroku не підтримує .NET.

6. Також, потрібно сказати heroku, де йому взяти Dockerfile. Для цього створюю heroku.yml на тому ж файловому рівні, що і Dockerfile

build:
    docker:
        web: Dockerfile

7. Далі до свого репозиторію (потрібно ініціалізувати якщо немає — git init) додаю посилання на репозиторій heroku.

git remote add heroku-demo git.heroku.com/topfighter-demo.git

8. До репозиторію потрібно додати Dockerfile і heroku.yml (потрібно й інші файли, якщо до цього вони не були в репозиторії)

git add .
git commit -m “Added heroku support”

9. Нарешті, потрібно запушати все до репозиторію heroku і після цього одразу почнеться розгортання додатку

10. Після успішного розгортання можна перейти за посиланням на додаток (крок 4) і побачити свій сайт.

Також в своєму кабінеті heroku можна подивитись стан свого додатку, логи, налаштування, видалити додаток, і т.д.

Висновки

Повертаючись до вимог, які я поставив до цього проекту, можна сказати, що їх було виконано. Всі три технології, про які йшлося в цій статті, були новими для мене. І все це вийшло абсолютно безкоштовно, не враховуючи доменного імені сайту, яке в разі потреби можна буде взяти в оренду (приблизно 10-15 доларів на рік).

Отже, й справді вийшло дешево та сердито, а такий стек технологій чудово підійде для маленьких додатків-хобі.

Корисні посилання:

  1. Сорси Blazor’а
  2. Документація Blazor
  3. Документація SQLite
  4. Heroku
  5. Крон джоби
👍НравитсяПонравилось14
В избранноеВ избранном4
LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

У хероку есть бесплатный инстанс Постгре и Редис. Проблему холодного старта можно решить периодическим пингом хоста изнутри приложения.

І все це вийшло абсолютно безкоштовно, не враховуючи доменного імені сайту, яке в разі потреби можна буде взяти в оренду (приблизно 10-15 доларів на рік).

Проблема в тім, що за $10-15 можна взяти повноцінну віртуалку
Тому, така схема ок для нульових затрат, щоб закинути софт і забути

усе, що було додано в БД (нагадую, що це просто файл) протягом роботи dyno зникає, адже коли dyno засинає, всі дані програми стираються, а коли dyno прокидається, все відновлюється з моменту останнього деплою;

Що в такій схемі заважає редагувати в себе на хості, коммітити і аплоадити різницю на хост

запит до сплячого dyno буде оброблятись дуже довго.

не дуже
+1-5сек

1) на жаль ще не зустрічав повноцінних віртуалок за 10-15$ на рік.
2) пробував схожі воркераунди, але вперся в те, що в хероку гіт репозиторії знаходиться кодова база і відповідно збирання докер зображення та деплой автоматично відбувається після пушу в репо, проте в самого додатку, коли він запущений, інша файлова структура, а не той самий гіт репозиторій. Якщо у ви вирішили цю проблему, буду дуже вдячний за солюшн.
3) в мене було більше хвилини.

1) тут $30/y www.vultr.com/...​ts/cloud-compute/#pricing
А ось тут можна по 10 знайти lowendbox.com

2)

інша файлова структура

Уф
Там треба buildpack робити для нестандартних випадків
Тому докер дійсно простіше

3) То я трошки прибрехав — 20сек для мікро проекту на пітоні.

Дайно в Heroku мають ефемерну файлову систему. Це значить, що після кожного рестарту дайно його файлова система повністю очищується. Рестарт дайно відбувається після кожного розгортання, вручну або раз на день, як частина нормального циклу управління дайно-формацією. Тому ваш хак з кронджобою просто відтягне трохи момент коли дані в SQLite базі будуть видалені назважди. Тому я вважаю, що використовувати SQLite з Heroku — поганий приклад. В Heroku є купа плагінів з Free планом які дають можливість використовувати повноцінну SQL базу даних. Найчастіше вони пропонують в безкоштовному плані 10 000 рядків у всіх таблицях. Наприклад, elements.heroku.com/addons/heroku-postgresql

теж користуюсь Postgres в Heroku, для тестових проектів все супер

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