לא רינדור בצד השרת אבל עדיין רוצים לזרז את הביצועים של אתר React? כדאי לנסות עיבוד מראש!
react-snap
היא ספרייה של צד שלישי שמעבדת מראש דפים מהאתר לקובצי HTML סטטיים. הפעולה הזו יכולה לשפר את זמני ההצגה של הצגת ראשון באפליקציה.
הנה השוואה בין אותה אפליקציה עם וללא עיבוד מראש שנטען בחיבור 3G ובמכשיר נייד:
למה זה שימושי?
בעיית הביצועים העיקרית באפליקציות גדולות עם דף יחיד היא שהמשתמש צריך להמתין לסיום ההורדה של חבילות ה-JavaScript שמהן מורכב האתר, לפני שיוכלו לראות תוכן אמיתי. ככל שהחבילות גדולות יותר, כך המשתמש צריך להמתין יותר זמן.
כדי לפתור את הבעיה, מפתחים רבים מיישמים את הגישה של רינדור האפליקציה בשרת במקום רק להפעיל אותה בדפדפן. בכל מעבר של דף/מסלול, קוד ה-HTML המלא נוצר בשרת ונשלח לדפדפן, וכך מקצר את זמן הצגת המוצר ב-First-Party, אבל מגיע בעלות איטית יותר של זמן עד בייט ראשון.
עיבוד מראש הוא שיטה נפרדת שהיא פחות מורכבת מעיבוד בשרת, אבל היא גם מספקת דרך לשפר את זמני הצגת המוצר בשלב הראשון באפליקציה שלכם. נעשה שימוש בדפדפן ללא GUI או ללא ממשק משתמש, כדי ליצור קובצי HTML סטטיים של כל מסלול במהלך build time. לאחר מכן אפשר לשלוח את הקבצים האלה יחד עם חבילות JavaScript שדרושות לאפליקציה.
תגובה-הצמדה
ב-react-snap
נעשה שימוש ב-Puppeteer כדי ליצור קובצי 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) לכל נתיב שנסרק. תוכלו לראות איך נראה המטען הייעודי של ה-HTML על ידי לחיצה על כתובת ה-URL של בקשת ה-HTML, ולאחר מכן לחיצה על הכרטיסייה Previews (תצוגות מקדימות) בכלי הפיתוח ל-Chrome.
הבזק של תוכן לא מעוצב
על אף שה-HTML הסטטי מעובד כמעט באופן מיידי, הוא עדיין נשאר ללא עיצוב כברירת מחדל, וזה עלול לגרום לבעיה בהצגת "הבזק של תוכן ללא עיצוב" (FOUC). זה בולט במיוחד אם משתמשים בספריית CSS-in-JS כדי ליצור סלקטורים, כי חבילת ה-JavaScript צריכה לסיים את הביצוע לפני שאפשר להחיל סגנונות.
כדי למנוע זאת, אפשר להוסיף ישירות ל-<head>
של מסמך ה-HTML את ה-CSS הקריטי, או את הכמות המינימלית של CSS שנדרשת לעיבוד הראשוני של הדף. react-snap
משתמש בספריית צד שלישי אחרת בשער, minimalcss
, כדי לחלץ CSS קריטי לנתיבים שונים. כדי להפעיל את האפשרות הזו, מציינים את הפרטים הבאים בקובץ package.json
:
"reactSnap": {
"inlineCss": true
}
בתצוגה המקדימה של התשובה בכלי הפיתוח ל-Chrome יוצג עכשיו הדף המעוצב עם שורות CSS חשובות.
סיכום
אם אתם לא נתיבי רינדור בצד השרת באפליקציה שלכם, השתמשו ב-react-snap
כדי לעבד מראש HTML סטטי למשתמשים.
- מתקינים אותה כתלות פיתוח, ומתחילים עם הגדרות ברירת המחדל בלבד.
- השתמשו באפשרות הניסיונית
inlineCss
כדי להטביע CSS קריטי אם הוא מתאים לאתר שלכם. - אם אתם משתמשים בפיצול קוד ברמת רכיב בתוך מסלולים כלשהם, הקפידו לא לעבד מראש את מצב הטעינה למשתמשים. בקובץ README של
react-snap
מופיע מידע מפורט יותר.