Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Server-Side Rendering (SSR) в опыте Python Developer
Да, имею прямой опыт с SSR
Да, я работал с SSR (Server-Side Rendering) в контексте Python backend, хотя SSR часто ассоциируют с фронтом. На backend SSR реализуется через рендеринг HTML на сервере и отправку клиенту.
Варианты SSR, с которыми я работал
1. Jinja2 + Flask/FastAPI (классический подход)
Включал рендеринг HTML-шаблонов на сервере:
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")
@app.get("/products/{product_id}")
async def get_product(request: Request, product_id: str):
product = await fetch_product_from_db(product_id)
return templates.TemplateResponse("product.html", {
"request": request,
"product": product,
"reviews": await fetch_reviews(product_id)
})
2. Асинхронный SSR с предзагрузкой данных
Оптимизировал SSR через параллельную загрузку зависимых данных:
import asyncio
from typing import Dict, Any
async def fetch_product_data(product_id: str) -> Dict[str, Any]:
product_task = fetch_product_from_db(product_id)
reviews_task = fetch_reviews(product_id)
similar_task = fetch_similar_products(product_id)
author_task = fetch_author_info(product_id)
product, reviews, similar, author = await asyncio.gather(
product_task,
reviews_task,
similar_task,
author_task
)
return {
"product": product,
"reviews": reviews,
"similar_products": similar,
"author": author
}
3. Кеширование рендеринга
Для статического контента кешировал отрендеренный HTML:
@app.get("/blog/{post_slug}")
async def get_blog_post(request: Request, post_slug: str):
cache_key = f"post:{post_slug}:v1"
cached_html = await redis.get(cache_key)
if cached_html:
return HTMLResponse(content=cached_html)
post = await fetch_post(post_slug)
html = templates.render("post.html", {"post": post})
await redis.setex(cache_key, 86400, html)
return HTMLResponse(content=html)
Проблемы SSR, которые я решал
1. Time to First Byte (TTFB)
Проблема: сервер долго рендерит. Решение: streaming response
from fastapi.responses import StreamingResponse
async def stream_product_response(product_id: str):
yield b"<html><body><h1>Product</h1>"
product = await fetch_product(product_id)
yield f"<div>{product.name}</div>".encode()
reviews = await fetch_reviews(product_id)
for review in reviews:
yield f"<p>{review.text}</p>".encode()
yield b"</body></html>"
@app.get("/products/{product_id}")
async def get_product_stream(product_id: str):
return StreamingResponse(
stream_product_response(product_id),
media_type="text/html"
)
2. Race conditions при параллельной обработке
Решение: lock pattern
import asyncio
from asyncio import Lock
cache_locks = {}
async def fetch_with_single_lock(key: str, fetch_func):
if key not in cache_locks:
cache_locks[key] = Lock()
async with cache_locks[key]:
cached = await redis.get(key)
if cached:
return cached
result = await fetch_func()
await redis.set(key, result)
return result
3. SEO и метаданные
Для корректного SEO нужны разные title/description:
@app.get("/blog/{post_slug}")
async def get_blog_post(request: Request, post_slug: str):
post = await fetch_post(post_slug)
return templates.TemplateResponse("post.html", {
"request": request,
"post": post,
"meta_title": post.title,
"meta_description": post.excerpt,
"meta_image": post.cover_image
})
SSR vs CSR (Client-Side Rendering)
| Характеристика | SSR | CSR |
|---|---|---|
| TTFB | Медленнее | Быстрее |
| Time to Interactive | Быстрее | Медленнее |
| SEO | Идеален | Требует инвестиций |
| Нагрузка на сервер | Высокая | Низкая |
Современный подход: Hybrid
В последних проектах переходил на гибридный подход:
# backend: FastAPI отправляет JSON API
@app.get("/api/v1/products/{product_id}")
async def get_product_api(product_id: str):
return await fetch_product(product_id)
# frontend: Next.js рендерит сам
Когда использовать SSR
✅ Используй если:
- Критичен SEO
- Нужна быстрая initial load
- Контент статичен
❌ Избегай если:
- Высокая интерактивность
- Пиковая нагрузка на сервер
Итог
ССР на Python backend — мощный инструмент для SEO и performance. Требует понимания bottleneck'ов: кеширование, асинхронность, streaming.