Динамічний попередній перегляд посилання в CSR-додатку

Коли ви ділитесь посиланням, добре, коли можна побачити попередній перегляд деяких деталей, таких як зображення чи заголовок. Це покращує комунікацію та обмін контентом. Це можливо за допомогою використання деяких мета-тегів.

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

pic

Коли ви вставляєте посилання в додатки, як-от Linkedin, Whatsapp або Slack, система виявляє посилання та отримує метадані, які зазвичай знаходяться в HTML.

Основні мета-теги включають:

  • Open Graph Tags (og:title, og:description, og:image тощо)
  • Twitter Card Tags (twitter:title, twitter:description тощо)
  • Основні HTML теги (

    ``` ## Як це зробити Тут ми можемо обслужити index.html за допомогою додатку на серверній стороні.
    Ми будемо використовувати простий додаток на Node.js для обслуговування нашого додатку, водночас обробляючи посилання, які містять динамічний контент.

Спочатку давайте створимо додаток Express для обслуговування зібраного додатку.

//server.js  
const express = require('express');  
const path = require('path');  
const fs = require('fs');  

const app = express();  
const PORT = 8000;  

// Обслуговуємо статичні файли з папки build додатку React  
app.use(express.static(path.join(__dirname, 'build')));  


// Резервний маршрут для інших шляхів, щоб обслуговувати index.html (для React Router)  
app.get('*', (req, res) => {  
 res.sendFile(path.join(__dirname, 'build', 'index.html'));  
});  

// Запускаємо сервер  
app.listen(PORT, () => {  
 console.log(`Сервер запущено на http://localhost:${PORT}`);  
});

Тепер зібрати та запустимо додаток

nmp run build && node server.js

Відвідайте localhost:8000, і ви побачите ваш фронтенд додаток.

Давайте додамо логіку для обробки маршруту попереднього перегляду посилання.

const express = require('express');  
const path = require('path');  
const fs = require('fs');  

const app = express();  
const PORT = 8000;  

// Обслуговуємо статичні файли з папки build додатку React  
app.use(express.static(path.join(__dirname, 'build')));  

// Маршрут для обробки сторінки профілю  
app.get('/profile/:id', async (req, res) => {  
 const profileId = req.params.id;  
 const apiUrl = `https://api.example.com/profile/${profileId}`;  

 try {  
 // Отримуємо деталі профілю з зовнішнього API  
 const response = await fetch(apiUrl);  
 if (!response.ok) {  
 throw new Error('Не вдалося отримати деталі профілю');  
 }  
 const profile = await response.json();  

 // Читаємо базовий файл index.html  
 const htmlFile = path.join(__dirname, 'build', 'index.html');  
 let html = fs.readFileSync(htmlFile, 'utf8');  

 // Вставляємо Open Graph, Twitter та інші мета-теги  
 const metaTags = `  








 `;  

 // Вставляємо мета-теги в секцію HTML  
 html = html.replace(  
 '',  
 `${metaTags}`  
 );  

 // Відправляємо змінений HTML  
 res.send(html);  
 } catch (error) {  
 console.error('Помилка при отриманні профілю:', error.message);  

 // Якщо виникла помилка, відправляємо необроблений index.html  
 const htmlFile = path.join(__dirname, 'build', 'index.html');  
 res.sendFile(htmlFile);  
 }  
});  

// Резервний маршрут для інших шляхів, щоб обслуговувати index.html (для React Router)  
app.get('*', (req, res) => {  
 res.sendFile(path.join(__dirname, 'build', 'index.html'));  
});  

// Запускаємо сервер  
app.listen(PORT, () => {  
 console.log(`Сервер запущено на http://localhost:${PORT}`);  
});

Коли ви відвідуєте localhost:8000/profile/:id (це буде www..com/profile/:id після розгортання), сервер надішле змінений HTML, а React обробить решту. Цього разу HTML міститиме необхідні мета-теги, що означає, що бот соціальної мережі отримає достатньо даних для відображення попереднього перегляду цього посилання.

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

Тестування

Тепер, коли ми завершили розробку, давайте знайдемо спосіб це протестувати. Оскільки соціальні мережі не отримують дані з localhost, ми не можемо протестувати це в розробницькому середовищі. Тому ми можемо:

  1. Отримати домен після розгортання додатку на сервісі та протестувати за допомогою цього URL
  2. Використовувати сервіс для тунелювання localhost (наприклад, ngrok)

Важливе

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

  1. Будьте обережні з розмірами зображень (наприклад, мінімум 200x200, максимум 1200x600)
    2.
    Розмір зображення також важливий (наприклад, не більше 8 МБ).
  2. Довжина заголовка повинна відповідати розмірам мобільного екрану.
  3. Опис має бути доданий як мета-тег.

Оптимізація

Якщо ви звернули увагу, ми надсилаємо запит до API на сервер для конкретного маршруту. Це означає, що коли користувач відвідує це посилання в браузері, ми відправляємо один запит на сервер і ще один на фронтенді для відображення сторінки. Давайте розглянемо кілька варіантів:

  1. Оскільки ми вже отримуємо дані на сервері, ми можемо вбудувати всі дані в HTML і використовувати їх на фронтенді. На сервері:
const profileScript = ``;  
html = html.replace(  
 '',  
 `${profileScript}`  
);

На фронтенді:

const profile = window.__PROFILE__;  
if (profile) {  
 console.log("Profile data:", profile);  
} else {  
 // Якщо дані не вбудовані, робимо запит для отримання профілю  
 fetch(`/api/profile/${id}`).then(res => res.json()).then(console.log);  
}
  1. Ми можемо кешувати відповіді на сервері, щоб не отримувати API кожного разу. (Але пам'ятайте, що кеш треба оновлювати через певний час, наприклад, кожні 5 хвилин)
const cache = new Map();  

app.get('/profile/:id', async (req, res) => {  
 const profileId = req.params.id;  

 // Спочатку перевіряємо кеш  
 if (cache.has(profileId)) {  
 return sendProfileHtml(res, cache.get(profileId));  
 }  

 // Отримуємо профіль та кешуємо результат  
 try {  
 const response = await fetch(apiUrl);  
 if (!response.ok) throw new Error('Помилка API');  
 const profile = await response.json();  
 cache.set(profileId, profile); // Кешуємо профіль  
 sendProfileHtml(res, profile);  
 } catch (error) {  
 res.sendFile(path.join(__dirname, 'build', 'index.html'));  
 }  
});  

function sendProfileHtml(res, profile) {  
 // Генеруємо HTML з мета-тегами та відправляємо  
}
  1. Ми можемо обробити це на рівні Nginx, використовуючи детекцію User-Agent. Боти, як WhatsApp, LinkedIn, Facebook тощо, відправляють специфічні заголовки User-Agent, коли запитують URL для попереднього перегляду посилань. Ми можемо налаштувати Nginx для розрізнення ботів і звичайних користувачів, надаючи різні відповіді відповідно до цього.
server {  
 listen 80;  
 server_name example.com;  

 root /path/to/your/build;  
 index index.html;  

 # Детектуємо ботів за User-Agent  
 set $is_bot 0;  

 if ($http_user_agent ~* (facebookexternalhit|Twitterbot|LinkedInBot|WhatsApp|Slackbot|Googlebot|Bingbot)) {  
 set $is_bot 1;  
 }  

 location / {  
 # Якщо це бот, перенаправляємо запит на Node.js сервер  
 if ($is_bot) {  
 proxy_pass http://localhost:8000; # Node.js додаток  
 break;  
 }  

 # Інакше, обслуговуємо статичні файли  
 try_files $uri /index.html;  
 }  

 location /static/ {  
 # Обслуговуємо статичні файли безпосередньо  
 expires 1y;  
 add_header Cache-Control "public";  
 }  
}

Додатково

Створимо Dockerfile для побудови і обслуговування додатку.

# Використовуємо базовий образ Node.js  
FROM node:20  

# Встановлюємо робочу директорію  
WORKDIR /app  

# Копіюємо package.json та package-lock.json  
COPY package*.json ./  

# Встановлюємо залежності  
RUN npm install  

# Копіюємо увесь проект в контейнер  
COPY . .  

# Будуємо додаток React  
RUN npm run build  

# Відкриваємо порт  
EXPOSE 8000  

# Запускаємо сервер Node.js  
CMD ["node", "server.js"]

Структура папок

/frontend-app  
├── /public # Публічні активи для додатку React  
│ ├── index.html # Основний HTML файл для React  
│ └── favicon.ico # Іконка сайту  
├── /src # Джерельні файли для додатку React  
│ ├── App.js # Основний компонент React  
│ ├── index.js # Точка входу для React  
│ └── styles.css # CSS файл для додатку  
├── /build # (Згенеровані) файли збірки React (після виконання `npm run build`)  
├── package.json # Файл пакету для React та серверних залежностей  
├── package-lock.json # Лок файл для залежностей  
├── server.js # Сервер Node.js для обслуговування додатку React  
├── Dockerfile # Dockerfile для побудови і запуску додатку  
└── README.md # Документація проекту (необов'язково)




Перекладено з: [Dynamic Link Preview in CSR App](https://medium.com/@onk.irfan/dynamic-link-preview-in-csr-app-4741fa5ee2d2)

Leave a Reply

Your email address will not be published. Required fields are marked *