עיבוד מראש של מסלולים באמצעות תגובה מהירה

אתם לא רוצים רינדור בצד השרת, אבל אתם עדיין רוצים לזרז את הביצועים של אתר React? כדאי לנסות את הרינדור מראש!

השירות react-snap הוא צד שלישי שמעבדת מראש דפים מהאתר לקובצי HTML סטטיים. מי יכול שיפור הצגת תמונה ראשונית במסך (FP) באפליקציה שלך.

הנה השוואה של אותה אפליקציה עם ובלי עיבוד מראש שנטענו במכשיר נייד ובחיבור 3G מדומה:

השוואת טעינה זה לצד זה. הגרסה שנעשה בה שימוש בעיבוד מראש נטענת ב-4.2 שניות מהר יותר.

למה זה שימושי?

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

כדי לפתור זאת, מפתחים רבים נוקטים את הגישה של עיבוד האפליקציה את השרת, במקום לאתחל אותו רק בדפדפן. בכל פעם מעבר דף/נתיב, ה-HTML המלא נוצר בשרת ונשלח אל לדפדפן, שמפחית את זמני הציור הראשונים אבל עולה מחיר הזמן עד בייט ראשון.

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

תגובה מהירה

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

npm install --save-dev react-snap

לאחר מכן צריך להוסיף סקריפט postbuild אל package.json:

"scripts": {
  //...
  "postbuild": "react-snap"
}

הפעולה הזו תריץ באופן אוטומטי את הפקודה react-snap בכל פעם build חדש של האפליקציות שנוספו (npm build).

הדבר האחרון שצריך לעשות הוא לשנות את אופן אתחול האפליקציה. משנים את הקובץ src/index.js להגדרות הבאות:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));
const rootElement = document.getElementById("root");

if (rootElement.hasChildNodes()) {
  ReactDOM.hydrate(<App />, rootElement);
} else {
  ReactDOM.render(<App />, rootElement);
}

במקום להשתמש רק ב-ReactDOM.render כדי לעבד את רכיב התגובה הבסיסי (root) ישירות ל-DOM, הוא בודק אם כבר קיימים צומתי צאצא כדי לקבוע אם תכנים של HTML עובדו מראש (או עברו רינדור שרת). במקרה כזה, במקום זאת, המערכת תשתמש ב-ReactDOM.hydrate כדי לצרף את האירוע שמאזינים ל-HTML שכבר נוצר, במקום ליצור אותו מחדש.

פיתוח האפליקציה ייצור עכשיו קובצי HTML סטטיים כמטענים ייעודיים (payloads) כל מסלול שנסרק. תוכל לבחון איך נראה המטען הייעודי (payload) של ה-HTML למשל, לוחצים על כתובת ה-URL של בקשת ה-HTML ואז לוחצים על Previews (תצוגה מקדימה) בכרטיסייה 'כלי פיתוח' ל-Chrome.

השוואה מסוג &#39;לפני ואחרי&#39;. הצילום שלאחר מכן מראה שהתוכן עבר רינדור.

Flash של תוכן ללא עיצוב

למרות ש-HTML סטטי מעובד כעת באופן כמעט מיידי, הוא עדיין נשאר ללא סגנון כברירת מחדל, מה שעלול לגרום לבעיה בהצגת "הבהוב של תוכן" (FOUC). זה עשוי להיות חשוב במיוחד אם אתם משתמשים ב-CSS-in-JS. הספרייה כדי ליצור סלקטורים, כי חבילת ה-JavaScript תצטרך להסתיים ביצוע לפני שניתן להחיל סגנונות כלשהם.

כדי למנוע מצב כזה, שירות ה-CSS הקריטי או הכמות המינימלית של CSS שנדרש לעיבוד הדף הראשוני, ניתן להוסיף ישירות אל <head> של מסמך ה-HTML. react-snap משתמש בספרייה אחרת של צד שלישי במסגרת את המכסה, minimalcss, כדי לחלץ שירות CSS קריטי למסלולים שונים. כדי להפעיל את האפשרות הזאת, צריך לציין הבאים בקובץ package.json:

"reactSnap": {
  "inlineCss": true
}

בתצוגה המקדימה של התשובה בכלי הפיתוח ל-Chrome תוכלו לראות עכשיו את הדף המעוצב עם טקסט קריטי של CSS.

השוואה מסוג &#39;לפני ואחרי&#39;. הצילום שאחרי הצילום מראה שהתוכן עבר רינדור ומסוגנן באמצעות רכיבי CSS קריטיים מודגשים.

סיכום

אם האפליקציה שלכם לא כוללת מסלולי רינדור בצד השרת, אפשר להשתמש ב react-snap כדי לעבד מראש HTML סטטי למשתמשים שלך.

  1. מתקינים אותו כתלות בפיתוח ומתחילים רק עם ברירת המחדל הגדרות.
  2. אפשר להשתמש באפשרות הניסיונית inlineCss כדי להטביע נכסים קריטיים של CSS אם היא פועלת לאתר שלך.
  3. אם אתם משתמשים בפיצול קוד ברמת הרכיב בתוך מסלולים כלשהם, הקפידו לא לעבד מראש את מצב הטעינה למשתמשים שלכם. react-snap קובץ README על הנושא הזה בפירוט רב יותר.