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