از پیش رندر مسیرها با react-snap

رندر سمت سرور نیست اما همچنان می خواهید عملکرد سایت React خود را افزایش دهید؟ پیش رندر را امتحان کنید!

react-snap یک کتابخانه شخص ثالث است که صفحات سایت شما را به فایل های HTML ایستا از قبل رندر می کند. این می تواند زمان First Paint را در برنامه شما بهبود بخشد.

در اینجا مقایسه ای از یک برنامه مشابه با و بدون پیش رندر بارگذاری شده در اتصال 3G شبیه سازی شده و دستگاه تلفن همراه آورده شده است:

مقایسه بارگذاری کنار هم. نسخه ای که از پیش رندر استفاده می کند 4.2 ثانیه سریعتر بارگیری می شود.

چرا این مفید است؟

مشکل اصلی عملکرد برنامه های بزرگ تک صفحه ای این است که کاربر باید منتظر بماند تا بسته(های) جاوا اسکریپت که سایت را تشکیل می دهند، دانلود شود تا بتواند محتوای واقعی را ببیند. هرچه بسته ها بزرگتر باشند، کاربر باید مدت بیشتری منتظر بماند.

برای حل این مشکل، بسیاری از توسعه‌دهندگان به جای اینکه فقط آن را در مرورگر راه‌اندازی کنند، روی سرور رندر می‌کنند. با هر انتقال صفحه/مسیر، HTML کامل بر روی سرور تولید می‌شود و به مرورگر ارسال می‌شود، که زمان First Paint را کاهش می‌دهد، اما هزینه زمانی کمتری به First Byte دارد.

پیش رندر یک تکنیک جداگانه است که پیچیدگی کمتری نسبت به رندر سرور دارد، اما راهی برای بهبود زمان First Paint در برنامه شما نیز فراهم می کند. یک مرورگر بدون هد یا یک مرورگر بدون رابط کاربری، برای تولید فایل‌های HTML ثابت هر مسیر در طول زمان ساخت استفاده می‌شود. سپس این فایل‌ها را می‌توان همراه با بسته‌های جاوا اسکریپت که برای برنامه مورد نیاز است، ارسال کرد.

واکنش نشان دادن

react-snap از Puppeteer برای ایجاد فایل های HTML از پیش رندر شده از مسیرهای مختلف در برنامه شما استفاده می کند. برای شروع، آن را به عنوان یک وابستگی توسعه نصب کنید:

npm install --save-dev react-snap

سپس یک اسکریپت postbuild را در package.json خود اضافه کنید:

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

این به طور خودکار دستور react-snap هر بار که یک بیلد جدید از برنامه های کاربردی ساخته می شود اجرا می کند ( 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 برای پیوست کردن شنوندگان رویداد به HTML از قبل ایجاد شده استفاده می شود.

ساختن برنامه اکنون فایل های HTML ایستا را به عنوان بار برای هر مسیری که خزیده می شود تولید می کند. می‌توانید با کلیک کردن روی URL درخواست HTML و سپس کلیک کردن روی برگه پیش‌نمایش‌ها در Chrome DevTools، نگاهی به ظاهر محموله HTML بیندازید.

مقایسه قبل و بعد عکس بعد نشان می دهد که محتوا رندر شده است.

فلش محتوای بدون استایل

اگرچه HTML ایستا اکنون تقریباً بلافاصله ارائه می‌شود، اما همچنان به‌طور پیش‌فرض بدون استایل باقی می‌ماند که ممکن است باعث بروز مشکل نمایش «فلش محتوای بدون استایل» (FOUC) شود. اگر از کتابخانه CSS-in-JS برای تولید انتخابگرها استفاده می کنید، این می تواند به ویژه قابل توجه باشد، زیرا بسته جاوا اسکریپت باید قبل از اعمال هر سبکی، اجرا را به پایان برساند.

برای کمک به جلوگیری از این امر، CSS حیاتی یا حداقل مقدار CSS که برای رندر صفحه اولیه لازم است، می‌تواند مستقیماً به <head> سند HTML وارد شود. react-snap از یک کتابخانه شخص ثالث دیگر، minimalcss برای استخراج هر CSS حیاتی برای مسیرهای مختلف استفاده می کند. شما می توانید این را با مشخص کردن موارد زیر در فایل package.json خود فعال کنید:

"reactSnap": {
  "inlineCss": true
}

با نگاهی به پیش‌نمایش پاسخ در Chrome DevTools، اکنون صفحه استایل‌دار با CSS حیاتی داخل آن نشان داده می‌شود.

مقایسه قبل و بعد عکس بعد نشان می دهد که محتوا رندر شده است و به دلیل CSS حیاتی خطی شده است.

نتیجه گیری

اگر در برنامه خود مسیرهای رندر سمت سرور نیستید، از react-snap برای پیش نمایش HTML ایستا برای کاربران خود استفاده کنید.

  1. آن را به عنوان یک وابستگی توسعه نصب کنید و فقط با تنظیمات پیش فرض شروع کنید.
  2. اگر برای سایت شما کار می کند، از گزینه آزمایشی inlineCss برای داخل کردن CSS حیاتی استفاده کنید.
  3. اگر از تقسیم کد در سطح مؤلفه در هر مسیری استفاده می کنید، مراقب باشید که وضعیت بارگیری را از قبل برای کاربران خود ارائه نکنید. react-snap README این موضوع را با جزئیات بیشتری پوشش می دهد.