العرض من الخادم (SSR) بقوالب Jinja
درس 4 من 5
4العرض من الخادم (SSR) بقوالب Jinja
الصورة الكبيرةفي SSR لا يستلم المتصفح JSON ثم يرسم بنفسه. الخادم يملأ قالبًا بالبيانات ويرسل HTML نهائيًا، فتظهر الصفحة فور وصولها حتى بلا JavaScript.
ماذا تشاهد في الرسم: رحلة طلب في SSR: الخادم هو من يرسم. المتصفح يستلم صفحة مكتملة ويعرضها مباشرة.
خارطة هذا الجزء
المفاهيم بالترتيب، اضغط أيًّا منها للقفز إليه:
طريقان إلى نفس الفكرة
تخيّل مطعمًا: في SSR يطبخ المطبخ الطبق كاملًا ويرسله لطاولتك جاهزًا. في الطريقة الأخرى يرسل لك المكوّنات وتطبخ أنت على الطاولة (JavaScript في المتصفح). الطبق الجاهز يصل أسرع للأكل، خصوصًا إذا كانت طاولتك (جوالك) بطيئة.
محرّك القوالب (Jinja2 في Flask وDjango بصيغة قريبة) يقيّم {{ expr }} و{% for %} و{% if %} ويطبّق الهروب التلقائي فيتحوّل < إلى <. الوراثة بـ {% extends "base.html" %} و{% block %} تعطي هيكلًا واحدًا لكل الصفحات. SSR يحسّن زمن أول عرض (FCP) والفهرسة، ويكلّف عمل خادم لكل طلب، ويُكمَّل عادةً بالتخزين المؤقت أو التوليد الثابت، أو بـ hydration حين تحتاج تفاعلًا كثيرًا.
قبل أن تبدأ
📨HTTP
تعرف الطلب والرد وأكواد الحالة.
🐍بايثون والدوال
تكتب دالة وتمرّر لها قاموسًا.
الفكرة الجوهرية
1القالب: نص فيه فراغات
القالب ملف HTML فيه أماكن للبيانات. محرّك القوالب يستبدل كل مكان بقيمته. هذا مثال بالمكتبة القياسية لترى الفكرة عارية، ثم نرى Jinja.
from string import Template
from html import escape
page = Template("<h1>$title</h1>\n<ul>\n$items</ul>")
menu = ["Espresso", "Latte", "<script>alert(1)</script>"]
items = "".join(f" <li>{escape(name)}</li>\n" for name in menu)
print(page.substitute(title="Menu", items=items))<script> يصبح كودًا يعمل في متصفح كل زائر (XSS). Jinja يهرب تلقائيًا، فلا تعطّله بـ |safe إلا لنص تثق به تمامًا.2Jinja: حلقات وشروط ووراثة
{{ }} لطباعة قيمة، و{% %} للتحكّم. القالب الأساسي يعرّف الهيكل والكتل، وكل صفحة تملأ الكتل فقط.
{# templates/base.html #}
<!doctype html>
<html lang="ar" dir="rtl">
<head><title>{% block title %}مقهى{% endblock %}</title></head>
<body>
<nav><a href="/">الرئيسية</a></nav>
<main>{% block content %}{% endblock %}</main>
</body>
</html>
{# templates/menu.html #}
{% extends "base.html" %}
{% block title %}القائمة{% endblock %}
{% block content %}
<h1>القائمة</h1>
{% if drinks %}
<ul>
{% for d in drinks %}
<li>{{ d.name }}: {{ d.price }} ر.س</li>
{% endfor %}
</ul>
{% else %}
<p>القائمة فارغة اليوم.</p>
{% endif %}
{% endblock %}3Flask: المسار يعرض القالب
المسار يجلب البيانات ويمرّرها لـ render_template. الرد HTML كامل بكود 200.
from flask import Flask, render_template, abort
app = Flask(__name__)
DRINKS = {1: {"name": "Latte", "price": 14}, 2: {"name": "Mocha", "price": 16}}
@app.get("/menu")
def menu():
return render_template("menu.html", drinks=list(DRINKS.values()))
@app.get("/drinks/<int:drink_id>")
def drink(drink_id):
item = DRINKS.get(drink_id)
if item is None:
abort(404)
return render_template("drink.html", drink=item)
# flask --app app run --debug4متى SSR ومتى تطبيق صفحة واحدة؟
SSR للمحتوى الذي يُقرأ ويُبحث عنه: متاجر، مدونات، صفحات منتجات، لوحات إدارة بسيطة. تطبيق الصفحة الواحدة (SPA) للأدوات شديدة التفاعل: محرّر، خريطة، لوحة رسوم حية. الأطر الحديثة مثل Next.js تخلط الاثنين: الخادم يرسم أولًا ثم React يتولّى التفاعل.
مثال محلول
المسألة: صفحة منتجات بـ React تظهر بيضاء ثانيتين على جوال بطيء، ومحرك البحث لا يرى الأسماء. التحليل: المتصفح يحمّل JS ثم يطلب JSON ثم يرسم. الحل: اعرض الصفحة من الخادم بقالب يملأ الأسماء والأسعار، فيصل HTML جاهزًا. الأزرار التفاعلية (أضف للسلة) تبقى JS صغيرًا فوق الصفحة.
خرافة مقابل حقيقة
| الخرافة | الحقيقة |
|---|---|
| SSR تقنية قديمة انتهت. | عادت بقوة: Next.js وRemix وDjango وRails كلها تعرض من الخادم، لأن السرعة والفهرسة مهمة. |
| SSR يعني بلا JavaScript أبدًا. | يعني أن الصفحة الأولى تأتي جاهزة. تستطيع أن تضيف JS للتفاعل فوقها. |
اختبر فهمك
من يبني HTML في SSR؟
الخادم يملأ القالب ويرسل HTML جاهزًا.
اسم منتج فيه <script> عُرض في Jinja بلا |safe. ماذا يحدث؟
الهروب التلقائي يحوّل < إلى < فلا يُنفَّذ شيء.
ما فائدة {% extends %}؟
هيكل واحد لكل الصفحات، وكل صفحة تكتب ما يخصّها.
بطاقات مراجعة سريعة
تحقق من فهمك
لماذا SSR أفضل للبحث؟
لأن المحتوى موجود في HTML المرسل نفسه، فلا يحتاج الزاحف تشغيل JavaScript ليراه.
ما تكلفة SSR؟
عمل على الخادم لكل طلب. نخففه بالتخزين المؤقت أو بالتوليد الثابت للصفحات التي لا تتغيّر.
متى تختار SPA؟
لأداة شديدة التفاعل يبقى فيها المستخدم طويلًا، مثل محرّر أو لوحة رسوم حية.
مصادر هذا الدرس
مرتّبة بالنوع. ابدأ بالتوثيق الرسمي إذا تبي المرجع الدقيق، وبالمقال أو الفيديو إذا تبي الشرح أولًا.
توثيق رسمي2
خلّصت الدرس؟
سجّل الدخول ليُحفظ تقدّمك.