เส้นทางที่แสดงผลล่วงหน้าด้วยฟีเจอร์ Snap-Snap

หากไม่มีการแสดงผลฝั่งเซิร์ฟเวอร์ แต่ยังต้องการเพิ่มประสิทธิภาพของเว็บไซต์ React อยู่ ลองแสดงผลล่วงหน้า

react-snap เป็นบุคคลที่สาม ที่แสดงผลล่วงหน้าของหน้าเว็บไซต์ของคุณเป็นไฟล์ HTML แบบคงที่ วิธีนี้ ปรับปรุง การแสดงผลครั้งแรก ครั้งในแอปพลิเคชันของคุณ

นี่คือการเปรียบเทียบแอปพลิเคชันเดียวกันที่มีและไม่มีการแสดงผลล่วงหน้า โหลดด้วยการเชื่อมต่อ 3G และอุปกรณ์เคลื่อนที่จำลอง:

วันที่ การเปรียบเทียบการโหลดแบบแสดงข้างกัน เวอร์ชันที่ใช้การแสดงผลล่วงหน้าจะโหลดได้เร็วขึ้น 4.2 วินาที

เหตุใดจึงมีประโยชน์

ปัญหาประสิทธิภาพที่สำคัญในแอปพลิเคชันหน้าเว็บเดียวขนาดใหญ่คือ ผู้ใช้ต้องรอให้ชุด JavaScript ที่ประกอบกันเป็นเว็บไซต์เสร็จ ก่อนที่พวกเขาจะได้ดูเนื้อหาจริง ยิ่งแพ็กเกจมีขนาดใหญ่ขึ้น ผู้ใช้ต้องรอนานขึ้น

เพื่อแก้ไขปัญหานี้ นักพัฒนาซอฟต์แวร์จำนวนมากจึงใช้แนวทางการแสดงผลแอปพลิเคชันใน แทนที่จะเปิดเครื่องเฉพาะบนเบราว์เซอร์ ใน การเปลี่ยนหน้า/เส้นทาง ระบบจะสร้าง HTML ที่สมบูรณ์บนเซิร์ฟเวอร์และส่งไปยัง ซึ่งเป็นเบราว์เซอร์ที่ลดเวลา First Paint ได้ แต่มาพร้อมกับค่าใช้จ่ายที่ช้ากว่า เวลาที่ได้รับข้อมูลไบต์แรก

การแสดงผลล่วงหน้าเป็นเทคนิคแยกต่างหากซึ่งมีความซับซ้อนน้อยกว่าเซิร์ฟเวอร์ และยังเป็นวิธีในการปรับปรุงการแสดงผล First Paint ใน แอปพลิเคชัน มีการใช้เบราว์เซอร์แบบไม่มีส่วนหัวหรือเบราว์เซอร์ที่ไม่มีอินเทอร์เฟซผู้ใช้ เพื่อสร้างไฟล์ HTML แบบคงที่ของทุกเส้นทางในระหว่างเวลาสร้าง ไฟล์เหล่านี้ สามารถส่งไปพร้อมกับกลุ่ม JavaScript ที่จำเป็นต้องใช้สำหรับ แอปพลิเคชัน

รีแอ็ก-สแนป

react-snap ใช้ Puppeteer เพื่อ สร้างไฟล์ HTML ที่แสดงผลล่วงหน้าของเส้นทางต่างๆ ในแอปพลิเคชันของคุณ ถึง เริ่มต้น ให้ติดตั้งเป็นทรัพยากร Dependency ในการพัฒนา

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 เพื่อแนบเหตุการณ์แทน Listener ของ HTML ที่สร้างไว้แล้ว แทนที่จะสร้างใหม่

การสร้างแอปพลิเคชันจะสร้างไฟล์ HTML แบบคงที่เป็นเพย์โหลดสำหรับ แต่ละเส้นทางที่มีการ Crawl คุณสามารถดูว่าเพย์โหลด HTML มีลักษณะอย่างไร เช่น โดยคลิก URL ของคำขอ HTML แล้วคลิกตัวอย่าง ภายในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome

การเปรียบเทียบก่อนและหลัง ภาพหลังการถ่ายทำแสดงว่าเนื้อหาแสดงผลแล้ว

Flash ของเนื้อหาที่ไม่ได้จัดรูปแบบ

แม้ว่าในขณะนี้ HTML แบบคงที่จะแสดงผลแทบจะในทันที แต่ HTML ก็ยังคงอยู่ ไม่มีการจัดรูปแบบโดยค่าเริ่มต้น ซึ่งอาจทำให้เกิดปัญหาในการแสดง "ไม่จัดรูปแบบ" เนื้อหา" (FOUC) โดยจะสังเกตเห็นได้ชัดหากคุณใช้ CSS-in-JS ไลบรารีในการสร้างตัวเลือกเนื่องจากแพ็กเกจ JavaScript จะต้องเสร็จสิ้น เกิดขึ้นก่อนจะนำไปใช้สไตล์ใดๆ ได้

เพื่อช่วยป้องกันปัญหานี้ คุณควร CSS ที่สำคัญ หรือจำนวน CSS ขั้นต่ำที่ ที่จำเป็นต่อการแสดงผลของหน้าเริ่มต้น คุณสามารถแทรกในบรรทัดไปยัง <head> โดยตรง ของเอกสาร HTML react-snap ใช้ไลบรารีอื่นของบุคคลที่สามภายใต้ ฮู้ด minimalcss เพื่อดึงข้อมูล CSS วิกฤติสำหรับเส้นทางต่างๆ คุณเปิดใช้งานได้โดยระบุ รายการต่อไปนี้ในไฟล์ package.json ของคุณ

"reactSnap": {
  "inlineCss": true
}

การดูตัวอย่างการตอบกลับใน Chrome DevTools จะแสดงหน้าที่มีการจัดรูปแบบซึ่งมี CSS ที่สำคัญแทรกในบรรทัด

การเปรียบเทียบก่อนและหลัง ภาพ &quot;หลังการถ่ายทำ&quot; แสดงให้เห็นว่าเนื้อหาแสดงผลแล้วและมีการจัดรูปแบบเนื่องจาก CSS ที่สำคัญในบรรทัด

บทสรุป

ถ้าคุณไม่ใช่เส้นทางการแสดงผลฝั่งเซิร์ฟเวอร์ในแอปพลิเคชันของคุณ ให้ใช้ react-snap เพื่อแสดง HTML แบบคงที่ต่อผู้ใช้ล่วงหน้า

  1. ติดตั้งเป็นทรัพยากร Dependency ของการพัฒนาและเริ่มต้นด้วยค่าเริ่มต้นเท่านั้น การตั้งค่า
  2. ใช้ตัวเลือก inlineCss แบบทดลองเพื่อแทรก CSS ที่สำคัญในหน้า หากใช้งานได้ สำหรับเว็บไซต์ของคุณ
  3. หากคุณใช้การแยกโค้ดในระดับคอมโพเนนต์ภายในเส้นทางใดก็ตาม โปรดระวังอย่าแสดงผลสถานะการโหลดล่วงหน้าให้ผู้ใช้ทราบ react-snap README ครอบคลุมถึงเรื่องนี้อย่างละเอียดยิ่งขึ้น