ארכיטקטורה ליישומי ריאקט

17/02/2025

יחד עם המעורבות של Vercel בליבה של ריאקט אנחנו רואים גם שינוי ארכיטקטורה בפיתוח יישומי ריאקט - מעבר מספריה לפיתוח קוד צד לקוח לפריימוורק לפיתוח Full Stack. בואו נראה מה האפשרויות שלנו היום ומתי כדאי לבחור כל אפשרות.

1. פיתוח Front End בריאקט וקוד צד שרת בתור REST API

ריאקט מסוגלת לעבוד בתור ספריית צד-לקוח ולהשתלב בכל פרויקט צד שרת שנבנה. האינטגרציה בין קוד צד השרת לקוד צד הלקוח מתבצעת במספר שלבים:

  1. בשלב הבנייה יהיה לנו מנגנון שיבנה את קבצי המקור (JSX או TSX) וימיר אותם לקבצי JavaScript שדפדפן יכול לקבל. לרוב אחרי הבניה אותו מנגנון גם יעתיק את כל הקבצים שנוצרו לתיקייה להפצה כמו dist או public.

  2. בשלב הפרודקשן לקוח יקבל אפליקציית ריאקט סטטית, האפליקציה תפנה לשרת כדי למשוך מידע בדרך כלל ב REST API ותשתמש במידע זה כדי להציג דברים על המסך. שינויים שקורים באפליקציה ינוהלו עם ספריות ניהול State בצד לקוח כמו רידאקס.

  3. אופטימיזציה מקובלת בשלב זה היא לשים את המידע הראשוני שהאפליקציה צריכה בתוך ה JavaScript באמצעות הגדרת משתנה על window מתוך קובץ ה HTML, מה שאומר שקובץ ה HTML יוגש מהשרת ולא מקובץ סטטי. הנה דוגמה מ PHP לשתול מידע לתוך ה JavaScript

<?php
// Example PHP data - you can modify this according to your needs
$data = [
    'user' => [
        'id' => 1,
        'name' => 'John Doe',
        'email' => 'john@example.com',
        'preferences' => [
            'theme' => 'dark',
            'notifications' => true
        ]
    ],
    'settings' => [
        'language' => 'en',
        'timezone' => 'UTC'
    ],
    'meta' => [
        'lastUpdated' => date('Y-m-d H:i:s'),
        'version' => '1.0.0'
    ]
];
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>State Management Example</title>
</head>
<body>
    <!-- Your HTML content here -->

    <script>
        // Initialize window.__state__ object
        window.__state__ = window.__state__ || {};

        // Safely encode PHP data as JSON and inject it into window.__state__
        window.__state__.data = <?php echo json_encode($data, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_PRETTY_PRINT); ?>;

        // Example of accessing the data
        console.log('User name:', window.__state__.data.user.name);
        console.log('Current theme:', window.__state__.data.user.preferences.theme);
    </script>
</body>
</html>

בצד של ריאקט או רידאקס, אנחנו לוקחים את המשתתנה window.__state__ בתור הערך הראשוני שממנו בונים את ה Store וממשיכים לנהל את השינויים כרגיל לפי פעולות משתמש באפליקציה.

היתרונות בגישה זו:

  1. אפשר לפתח ולבדוק קוד צד לקוח וקוד צד שרת בנפרד.

  2. אפשר להשתמש באותו API בצד שרת גם לאפליקציית מובייל, אפילו שהיא כתובה בשפה אחרת לגמרי.

2. פיתוח מערכת Full Stack בריאקט עם Next

היתרונות בגישת ה API ברורים אבל מהם גם ברור לנו מה החסרונות: המערכת שלנו צריכה לכלול קוד שימשוך מידע מהשרת ויפענח אותו, נדרש תיאום בין קוד צד לקוח לקוד צד שרת בממשקים (מה שמשפיע על קצב הפיתוח ועל קצב העבודה ב Refactoring).

בנוסף דפדפן שמגיע לאתר מקבל קבצי JavaScript ורק אחרי פיענוח והרצת ה JavaScript אפשר לראות את האתר. קוד ה JavaScript עשוי להיות ארוך בהרבה מה HTML שהוא יוצר וכך אנחנו מעבירים עודף מידע ברשת.

בתיעוד של ריאקט הדף שמספר על יצירת פרויקט ממליץ על שימוש בפריימוורק - כלומר ממליץ ליצור פרויקט עם next, remix או expo. הבלוק האחרון בעמוד מזכיר את Tanstack Start ו Redwood, שני פריימוורקים נוספים לפיתוח Full Stack. בהתיחס ל vite, שזו האופציה הקלאסית לפיתוח קוד צד לקוח בלבד, מספרים לנו שם שהם ממליצים על vite רק כשמוסיפים את ריאקט לפרויקט קיים או אם בונים פריימוורק, מה שמראה לנו בצורה ברורה את הכיוון של צוות ריאקט.

לכן האופציה השניה והיום לפחות לפי התיעוד של React היא גם המומלצת היא פיתוח מוצר Full Stack עם ריאקט כחלק מפריימוורק גדול יותר. פריימוורקים מציעים לנו את האופציה לבנות את הפרויקט בתור קוד צד לקוח בלבד, אבל לרוב הם יעודדו אותנו לבחור בארכיטקטורה מקיפה הכוללת קוד שרת וקוד לקוח, וזה אומר:

  1. קוד צד שרת מכיר את קבצי ה JSX או TSX של הפרויקט ומריץ אותם בתגובה לבקשה מדפדפן כדי להחזיר לדפדפן דף HTML מוכן להצגה.

  2. קוד JavaScript יצורף לעמוד ה HTML שנשלח כדי להוסיף אינטרקטיביות לעמוד (קומפוננטות צד לקוח). קוד ה JavaScript מתחיל תמיד מ State ראשוני שנטען מהשרת.

  3. פעולות בצד הלקוח יכולות להשפיע על השרת, ואז נשתמש במנגנונים של ריאקט (Server Actions) כדי לשלוח הודעה מהלקוח לשרת, הודעה שמבחינת הקוד נראית כמו קריאה רגילה לפונקציה. הפריימוורק אחראי על כתיבת קוד ה fetch ופיענוח התשובה בשבילנו.

  4. אין כמעט הצדקה להשתמש ב Redux או ספריות ניהול סטייט צד לקוח מתוחכמות באפליקציות כאלה, כי אין כמעט סטייט. כל שינוי בצד לקוח מיד מדווח לשרת או מנוהל ברמת הקומפוננטה.

היתרון המרכזי באפליקציות Full Stack הוא הפשטות. אפליקציה כזאת דורשת הרבה פחות חיבורים בשביל לעבוד וכוללת הרבה פחות קוד בהשוואה לאפליקציה בקוד ה Front End מופרד מקוד ה Back End. החיסרון הוא הנעילה לתוך הפריימוורק והקושי לשלב את הקוד עם Clients אחרים כמו אפליקציית מובייל.