
ความชุ่มชื้นบางส่วนสำหรับ next.js กับ preact x
คำอธิบาย: ในฤดูใบไม้ผลิเรากำลังสร้างเว็บไซต์สำหรับหนังสือพิมพ์และเราก็ตระหนักถึงประสิทธิภาพ มาก
หนังสือพิมพ์ส่วนใหญ่เป็นหน้าคงที่ ตอนนี้ถ้าเราจะสร้างแอปพลิเคชันหน้าเดียวเราจะสร้างชุดใหญ่ที่มีรหัสที่ไม่จำเป็นเป็นส่วนใหญ่
นี่ไม่เพียง แต่หมายความว่าผู้ใช้รอไฟล์ขนาดใหญ่ที่จะดาวน์โหลด แต่เนื่องจาก Addy Osmami ชี้ให้เห็นว่ามีค่าใช้จ่ายสูงในการปฏิบัติงานด้วยการแยกวิเคราะห์และดำเนินการรหัส เป็นกฎที่คลุมเครือของนิ้วหัวแม่มือเราสามารถพูดได้ว่ายิ่งมัดของคุณยิ่งใหญ่เท่าไหร่การแสดงของคุณก็ยิ่งแย่ลงเท่านั้น
นั่นคือเหตุผลที่เราตั้งเป้าหมายที่จะตัดขนาดชุดโดยการจัดส่งรหัสที่เราต้องการในไคลเอนต์จริงและปล่อยให้ส่วนที่เหลืออยู่ในการแสดงผลด้านเซิร์ฟเวอร์
repo นี้ยังคงเป็นข้อพิสูจน์แนวคิดเราจะดำเนินการต่อไปและใช้งานของเราเป็น 2 แพ็คเกจ:
pool-attendant-preact ห้องสมุดที่ใช้ความชุ่มชื้นส่วนหนึ่งกับ preact xnext-super-performance ปลั๊กอิน next.js ที่ใช้การตอบโต้พูลผู้เข้าร่วมเพื่อปรับปรุงประสิทธิภาพด้านไคลเอ็นต์ ด้านบนของความชุ่มชื้นบางส่วนเราจะใช้กลยุทธ์การโหลดรวมถึง critical CSS , critical JS , lazy loading , การ preloading ressources ฯลฯ ซึ่งเป็นส่วนหนึ่งของประสิทธิภาพการดำเนินงานครั้งต่อไป
สำหรับตอนนี้เรามี POC ไฮเดรชั่นบางส่วนสำหรับ next.js และนี่คือวิธีการทำงาน เมื่อคุณสร้าง next.config.js และใช้ปลั๊กอินของเราเช่นนั้น
const withSuperPerformance = require ( "next-super-performance" ) ;
module . exports = withSuperPerformance ( ) ;2 สิ่งจะเกิดขึ้น:
React จะถูกแทนที่ด้วย Preact เนื่องจากเป็นเพียง 3KB นั่นหมายความว่าคุณต้องสร้าง client.js ในโฟลเดอร์รูทของแอปของคุณซึ่งจะทำหน้าที่เป็นจุดเริ่มต้นสำหรับ JavaScript ที่จะส่งไปยังไคลเอนต์ เราทำสิ่งนี้เพื่อให้คุณควบคุมสิ่งที่คุณต้องการให้ผู้ใช้ดาวน์โหลดได้อย่างเต็มที่และที่สำคัญมากคือการเลือกกลยุทธ์การโหลดที่เหมาะกับคุณ
ตอนนี้ pool-attendant-preact เข้ามาเล่น Pool-Attendant-Preact Export 3 API สำหรับคุณ:
withHydration ความสำคัญกับการช่วยให้คุณทำเครื่องหมายส่วนประกอบของคุณเพื่อความชุ่มชื้นhydrate ฟังก์ชั่นเพื่อให้ความชุ่มชื้นส่วนประกอบที่ทำเครื่องหมายไว้ในไคลเอนต์HydrationData ส่วนประกอบที่เขียนอุปกรณ์ประกอบฉากต่อเนื่องไปยังไคลเอนต์เช่น NEXT_DATA 
มาอธิบายเรื่องนี้กันเถอะ สมมติว่าคุณมีแอพถัดไปที่มี header ส่วน main และ teaser S (ซึ่งอาจเป็นรูปภาพที่มีข้อความและพาดหัวเป็นต้น) เพื่อประโยชน์ของตัวอย่างนี้ลองทำทีเซอร์ 2 & 3 ไดนามิก (เพียงแค่เลือกบางรายการในหน้า) และปล่อยให้ส่วนที่เหลือคงที่
นี่คือวิธีที่คุณจะทำ:
ติดตั้งประสิทธิภาพต่อไป
npm i next-super-performance --save สร้าง next.config.js และใช้ปลั๊กอิน
const withSuperPerformance = require ( "next-super-performance" ) ;
module . exports = withSuperPerformance ( ) ; ปรับเปลี่ยน package.json ของคุณเพื่อใช้งานต่อไป preact อย่างถูกต้อง (สิ่งนี้จะมี react ต่อ preact จากนั้นเริ่มสคริปต์ถัดไปดั้งเดิมโดยไม่ต้องแก้ไข):
"scripts" : {
"dev" : "next:performance dev" ,
"start" : "next:performance start" ,
"build" : "next:performance build"
} , สร้าง pages/index.js
import Header from "../components/header" ;
import Main from "../components/main" ;
import { HydrationData } from "next-super-performance" ;
export default function Home ( ) {
return (
< section >
< Header />
< Main />
< HydrationData />
</ section >
) ;
} ส่วนสำคัญที่นี่คือ <HydrationData /> ซึ่งจะแทรกอะไรเช่นนี้:
< script type =" application/hydration-data " >
{ "1" : { "name" : "Teaser" , "props" : { "column" : 2 } } , "2" : { "name" : "Teaser" , "props" : { "column" : 3 } } }
</ script >นี่คือชื่อและอุปกรณ์ประกอบฉากของส่วนประกอบที่จะให้ความชุ่มชื้น
เพื่อบอกแอปของคุณว่าควรใช้ส่วนประกอบเฉพาะให้ใช้ withHydration ชุ่มชื้น main.js ของเราอาจมีลักษณะเช่นนี้:
import Teaser from "./teaser" ;
import { withHydration } from "next-super-performance" ;
const HydratedTeaser = withHydration ( Teaser ) ;
export default function Body ( ) {
return (
< main >
< Teaser column = { 1 } />
< HydratedTeaser column = { 2 } />
< HydratedTeaser column = { 3 } />
< Teaser column = { 1 } />
< Teaser column = { 2 } />
< Teaser column = { 3 } />
< Teaser column = { 1 } />
< Teaser column = { 2 } />
< Teaser column = { 3 } />
</ main >
) ;
}ในบรรทัดที่ 4 เราได้สร้างส่วนประกอบที่จะให้ความชุ่มชื้นในไคลเอนต์และเราใช้มัน 2 ครั้งในหน้าของเราด้วยอุปกรณ์ประกอบฉากที่แตกต่างกัน
withHydration จะเตรียมส่วนประกอบของคุณด้วย เครื่องหมาย เพื่อให้สามารถแสดงผลบนเซิร์ฟเวอร์และพบได้ใน HTML ของคุณบนไคลเอนต์ ดังนั้น <HydratedTeaser column={2} /> จะกลายเป็น
< Fragment >
< script type = "application/hydration-marker" />
< Teaser column = { 2 } />
</ Fragment > ส่วนสุดท้ายและส่วนสำคัญที่สุดคือ client.js ของคุณ js ซึ่งเป็นรหัสที่จะจัดส่งไปยังผู้ใช้ของคุณและซึ่งเป็นที่ที่คุณจะให้ความชุ่มชื้นส่วนประกอบของคุณ สำหรับส่วนประกอบเดียว ( Teaser ) มันอาจเป็นเรื่องง่าย
import { hydrate } from "next-super-performance" ;
import Teaser from "./components/teaser" ;
hydrate ( [ Teaser ] ) ; โอ้ next-super-performance มาพร้อมกับ pool-attendant-preact ซึ่งเป็นสาเหตุที่คุณนำเข้าทุกอย่างจากที่นี่แทนที่จะมาจาก pool-attendant-preact มันเพียงแค่นำเข้าและส่งออก withHydration hydrate และ HydrationData เพื่อความสะดวก
hydrate จะพบส่วนประกอบที่คุณทำเครื่องหมายโดยใช้ withHydration และใช้ข้อมูลจาก <HydrationData /> เพื่อให้ความชุ่มชื้นกับส่วนประกอบที่คุณส่งผ่านเป็นอาร์เรย์
สิ่งนี้จะทำให้คุณต้องนำเข้าส่วนประกอบที่คุณต้องการใช้ในไคลเอนต์ (และส่งผ่านไปยังฟังก์ชั่น hydrate ) เนื่องจาก client.js เป็นจุดเริ่มต้นสำหรับรหัสไคลเอนต์ทั้งหมดของคุณจึงหมายความว่าคุณจะเห็นและควบคุมรหัสที่คุณส่งไปยังผู้ใช้ของคุณ นอกเหนือจากการจัดส่งล่วงหน้าจะไม่มีการจัดส่งอีกแล้ว
หากส่วนประกอบของคุณมีการพึ่งพาด้วยตนเองการพึ่งพาเหล่านั้นจะเป็น "natuarally" จัดส่งเช่นกันเพราะ client.js เป็นรายการของคุณและทุกการพึ่งพาอาศัยกันจะได้รับการแก้ไขผ่าน WebPack
repo นี้เป็น POC และสิ่งที่เราจะสร้างต่อไป หากต้องการลองทำสิ่งนี้ให้โคลนที่เก็บนี้แล้วเรียกใช้
# Init Preact Git Sumodule
git submodule init
git submodule update
# Install dependencies
yarn
# Build Preact
cd packages/preact
yarn build
# Build the pool-attendant-preact package
# └─ cd to the pool-attendant-preact dir
cd ...
cd packages/pool-attendant-preact
# └─ build the package
yarn build
# cd to the app dir
cd ...
cd packages/app
# run the app
yarn dev ดูเหมือนว่า POC นี้จะทำงานได้ค่อนข้างดีเราสามารถลดขนาดชุดของเราได้อย่างมาก ยังมีอีกมากที่ต้องทำ Next.js ยังคงรวมรหัสที่เราไม่ต้องการเห็นในไคลเอนต์ (เช่น core-js ) นอกจากนี้เราตั้งเป้าหมายที่จะใช้เครื่องมือและ API เพื่อสร้างภาษาสำหรับแง่มุมที่สำคัญของรหัสเพื่อให้คุณมีเครื่องมือในการกำหนดเส้นทางการเรนเดอร์ที่สำคัญของคุณ