Як побудувати статичну версію Reddit?
Розмірковую над тим як побудувати статичний сайт подобний до Reddit
Подумаємо з яких частин складається Редіт і як максимально перевести їх у статику, щоб отрмати максимальну продуктивність? Назва проєкта – Shreddit (_sh_tatic reddit).
Редіт складається з:
- Сторінка посту
- Сторінка спільноти, яка складається з мєтаінформації та постів
- Користувач, який складається з метаінформації: підписки, посилання на пости, посилання на реакції
- Стрічки користувача, яка складається з оновлень від спільнот на які підписан користувач
Користувач може:
- Авторизуватися
- Подивитися стрічку останніх повідомлень у спільнотах
- Створити пост
- Створити коментар до посту
- Отримати сповіщення про новий коментар до посту
- Оцінити пост
- Оцінити коментар
- Шукати пости або інших користувачів
Сторінка посту
Нехай пост буде статичним файлом, який ми будемо класти у S3 /:community/:year/:month/:day/:slug/index.html
. Файл буде складатися з мета-даних та контента, та підключених shreddit.js
, shreddit.css
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Перший пост на Shreddit</title>
<meta name="description" content="Shreddit – це статично-згенерований аналог Reddit" />
<meta name="keywords" content="Reddit, Shreddit" />
<meta name="author" content="username" />
<!-- В цьому місці будуть Open Graph метатеги -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/shreddit/main.css" />
</head>
<body>
<main>
<h1>Перший пост на Shreddit</h1>
<p>Текст посту</p>
</main>
<script src="https://cdn.jsdelivr.net/npm/shreddit/main.js" defer></script>
</body>
</html>
Основна робота по відображенню сайта покладається на файли main.css
та main.css
. Вони загружають базові стилі, щоб контейнер main був у відповідному місці, бібліотеку Turbo, щоб були плавні переходи між сторінками. Після підвантаження основних стилів – зʼявиться шапка, ліва та права панелі.
Таким чином ми одразу показуємо контент, а через деякий час підвантажуються додаткові частини. Контент одразу знаходиться в CDN і віддається з максимальною ефективністю.
Створення посту буде відбуватися наступним чином
- Округляється поточні хвилини до десятих, якщо 03 – буде 0, якщо 5 – буде 10
- Якщо файл
/:community/:username/:year/:month/:day/:hour/:minute/index.html
вже існує, то користувачу потрібно почекати 10 хвилин щоб створити новий пост - Створюється файл з контентом посту:
/:community/:username/:year/:month/:day/:hour/:minute/index.html
- Створюється файл:
/logs/:year/:month/:day/:username+:community
Скрипт, який формує стрічку /:community/feed.xml
Для того щоб мати можливість збирати оновлення зі всіх комьюніті на котрі підписан користувач, потрібен скріпт який буде кожні 10 хвилин робити наступну роботу:
- Зчитує всі файли
:username+:community
з/logs/:year/:month/:day/
- Відкриває по черзі файл
/:community/lock.yml
- Якщо файл
lock.yml
існує та час в файлу меньше 10 хвилин, то скрипт пропускає поточну диркторію/:community
, якщо файл не існує або час більше 10 хвилин, то записуємо поточний час в файл - Намагаємся зчитати файл
/:community/:username/:year/:month/:day/:hour/:minute/index.html
міняючи:hour
від0
до23
та:minute
на0
,10
,20
,30
,40
,50
,60
. Зчитаний файл парсимо, дістаючи заголовок, обкладинку і зберігаємо в масив - Коли зчитали всі файли за весь день, формуємо
/:community/:year/:month/:day/feed.xml
та/:username/today.xml
з попередньо збереженого масива
Скрипт, який формує стрічку /:username/feed.xml
- Зчитує назви комьюніті і користувачів з
/logs/:year/:month/:day/
- Відкриває по черзі файл
/:username/lock.yml
- Якщо файл
lock.yml
існує та час в файлу меньше 10 хвилин, то скрипт пропускає поточну диркторію/:community
, якщо файл не існує або час більше 10 хвилин, то записуємо поточний час в файл - Намагаємся зчитати файл
/:community/:username/:year/:month/:day/:hour/:minute/index.html
міняючи:hour
від0
до23
та:minute
на0
,10
,20
,30
,40
,50
,60
. Зчитаний файл парсимо, дістаючи заголовок, обкладинку і зберігаємо в масив для конкретного користувача - Коли зчитали всі файли за весь день, формуємо
/:username/:year/:month/:day/feed.xml
та/:username/today.xml
з попередньо збереженого масива для кожного користувача
Стрічка користувача
Принцип формування стрчки користувача буде схож з тим як формується стрічка через RSS рідер. У користувача є файл /:username/subscriptions.yml
:
1
2
3
4
5
6
communities:
- community1
- community2
users:
- username1
- username2
Зчитуємо для кожного комьюніті та користувача файли /:community/:year/:month/:day/feed.xml
та /:username/:year/:month/:day/feed.xml
та кладемо їх до localStorage
. Дані зі стрічки за сьогодні повинні обновлюватися в localStorage
, дані за попередні дні можно зчитувати по мірі прокрутки стрічки.
Авторизація
Авторизацію треба робити через JWT. Авторизація може відбуватися через OAuth сервіс, наприклад, Google. Можно авторизовувати через Email, відправляючи посиляння для авторизації. Далі генерується JWT токен в Cloudflare функції та відправляється на клієнт, зберігається в localStorage
.
Створення посту
Для створення посту теж потрібна Cloudflare функція, котра буде перевіряти ключ, створювати або оновлювати файл посту.