مهندس برمجيات & مطور ويب

SSR و SSG المتقدمة باستخدام Spring Boot وReact

SSR و SSG المتقدمة باستخدام Spring Boot وReact

مقالك السابق حول عرض React من جهة الخادم باستخدام Spring Boot حاز على اهتمام كبير. في هذا المقال، نغوص أعمق لنشرح مفاهيم متقدمة مثل توليد الصفحات الثابتة (SSG)، تقنيات تهيئة React (Hydration)، ونشر المشاريع باستخدام Docker وCI/CD.

1. الفرق بين SSR و SSG

SSR (العرض من جهة الخادم) يعني أن يتم توليد HTML بواسطة React على الخادم عند كل طلب. أما SSG (توليد الصفحات الثابتة)، فيعني توليد HTML أثناء البناء فقط.

  • تحسين SEO (عناكب البحث ترى HTML كامل)
  • تجربة أسرع للمستخدم عند أول تحميل
  • أداء أعلى عندما يتم التخزين مؤقتًا

SSG مناسب للمحتوى الثابت، وSSR مطلوب عندما يكون المحتوى ديناميكيًا حسب الطلب.

2. استعراض: SSR باستخدام Spring Boot و Thymeleaf

كما شرحت سابقًا، يمكن عرض الصفحة باستخدام Thymeleaf داخل Spring Boot:

// Controller
@GetMapping("/")
public String index(Model model) {
  model.addAttribute("data", myService.getData());
  return "index";
}

لكن الدمج المباشر بين Thymeleaf وReact قد يكون محدودًا من حيث المرونة. لذلك نقدم بدائل أقوى أدناه.

3. الخيار الأول: SSR باستخدام Express و React و Spring API

دع Spring Boot يتعامل مع API فقط، بينما يقوم Express (Node.js) بعرض تطبيق React من جهة الخادم:

3.1 مثال على إعداد Express

// server.js
import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import App from './App';
import fs from 'fs';
import path from 'path';

const app = express();
app.use(express.static('build'));

app.get('*', (req, res) => {
  const html = renderToString(<App />);
  const indexHtml = fs.readFileSync(path.resolve('./build/index.html'), 'utf8');
  const finalHtml = indexHtml.replace('<div id="root"></div>', `<div id="root">${html}</div>`);
  res.send(finalHtml);
});

app.listen(3000);

3.2 لماذا هذا الخيار جيد؟

  • يحافظ على React كمشروع مستقل بالكامل
  • تحكم دقيق في العرض والتحديث
  • يمكنك الربط بسهولة مع API من Spring

4. الخيار الثاني: توليد الصفحات الثابتة SSG

يمكنك استخدام أدوات مثل react-snap أو vite-plugin-ssg لتوليد HTML أثناء البناء.

npx react-snap
// أو مع Vite
npm i vite-plugin-ssg

ثم يمكن لـ Spring Boot تقديم هذه الصفحات من خلال مجلد /static أو عن طريق CDN خارجي.

5. تحسين THydration في React

بعد عرض React من الخادم، يجب "تهيئة" React على المتصفح. إليك بعض التقنيات:

  • استخدام react-lazy-hydration لتأجيل التهيئة
  • استخدام React.lazy() و Suspense لتقسيم الكود
  • تهيئة الأجزاء المرئية فقط (Islands Architecture)
import { lazyHydrate } from 'react-lazy-hydration';

lazyHydrate(() => import('./HeavyComponent'), { whenVisible: true });

6. التخزين المؤقت و CDN

  • ضبط رؤوس HTTP باستخدام Spring Boot
  • استخدام Cloudflare أو CloudFront لتقديم الملفات الثابتة
@Configuration
public class CacheConfig implements WebMvcConfigurer {
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/static/**")
      .addResourceLocations("classpath:/static/")
      .setCachePeriod(31556926);
  }
}

7. تحسينات SEO

  • استخدام react-helmet لإضافة title و meta من الخادم
  • دعم Open Graph، Twitter Card، JSON-LD

8. النشر باستخدام Docker و CI/CD

استخدم Docker متعدد المراحل لتجميع React و Spring Boot معًا:

# Dockerfile
FROM node:18 as frontend
WORKDIR /app
COPY client/ .
RUN npm install && npm run build

FROM maven:3.8-jdk-17 as backend
WORKDIR /app
COPY server/ .
RUN mvn clean package

FROM openjdk:17
WORKDIR /app
COPY --from=frontend /app/build /app/static
COPY --from=backend /app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

9. مقارنة بين SSR و SSG

الميزة SSR SSG
أداء التحميل الأول أبطأ قليلاً 🚀 سريع جدًا
SEO ✅ ممتاز ✅ ممتاز
بيانات ديناميكية ✅ مخصص لكل طلب ⚠️ محدود
التوسعة يتطلب خادم نشط ✅ يعتمد على التخزين المؤقت
سهولة التطوير أعقد أسهل وأسرع

10. الخلاصة

أصبحت الآن قادرًا على:

  • تطبيق SSR أو SSG بحسب نوع مشروعك
  • تحسين تجربة المستخدم باستخدام Hydration متقدم
  • نشر التطبيق على شكل حاوية (Docker) قابلة للتوسعة

في المقال القادم: سنتحدث عن التوثيق، التحكم بالأدوار، وصفحات SSR المحمية للمستخدمين المسجلين.

أضف تعليق