[Frontend System Design]: มาเข้าใจการทำงานของ Lazy loading และ Code splitting ใน Bundler กัน

ในยุคที่เว็บแอปไม่ได้มีแค่หน้า HTML และไฟล์ JS เล็ก ๆ อีกต่อไป แต่เต็มไปด้วยฟีเจอร์ซับซ้อนและโค้ดจำนวนมาก การโหลดทุกอย่างในครั้งเดียวอาจทำให้ผู้ใช้ต้องรอนานกว่าจะเริ่มใช้งานได้จริง นี่คือเหตุผลที่ Bundler กลายมาเป็นเครื่องมือสำคัญ, ไม่ใช่แค่รวมไฟล์ แต่ยัง "Chunk" และ "Serve" โค้ดอย่างชาญฉลาดผ่านเทคนิค Code Splitting และ Lazy Loading เพื่อให้เว็บทั้งเร็วและประหยัดพลังงาน
sandwiched-developer-how-lazy-loading-และ-code-split-works

รู้จัก Bundler

ให้นึกภาพ “โรงงานประกอบ” ที่รับชิ้นส่วนโค้ดจากหลายแหล่ง มาผลิตเป็นไฟล์ที่ browser เปิดได้เร็วและปลอดภัย.ซึ่งเหตุผลที่ ต้องมีสิ่งนี้เพราะในปัจจุบัน module ที่เราใช้กัน project มีความหลากหายและซับซ้อนเกิดกว่า browser เราจะเข้าใจและรับได้ตรงๆ เช่น

  • ESNext Syntax (optional chaining, async/await)
  • TypeScript
  • SCSS/Sass
  • การโหลด asset ด้วย import logo from './logo.png'

ซึ่ง browser เปิดไฟล์พวกนี้ตรงๆไม่ได้ bundler จึงเข้ามาแก้ไขส่วนนี้

ซึ้งผมจะอธิบายการทำงานของ bundler เป็น diagram ทุกคนจะเห็นภาพได้ง่ายๆดังนี้

sandwiched-developer-bundler-workflow
sandwiched-developer-bundler-workflow

เราจะเห็นว่า bundler process นั้นมีกระบวนการเยอะแยะมากมายแต่ จะมีสองส่วนหลักๆที่สำคัญมากนั้นคือ การทำ Code Splitting อยู่ในขั้นตอน Optimization (Build Time) , Lazy Loading อยู่ในขั้นตอน Runtime (Run Time)

Code Splitting (Build time)

คือการ “แยกโค้ดออกเป็นหลายก้อน (chunks)” แทนที่จะรวมทุกอย่างไว้ในไฟล์เดียว เพื่อให้ตอนรันจริง (runtime) เบราว์เซอร์โหลดเฉพาะสิ่งที่ต้องใช้ ซึ่งจะช่วยลด initial load time และเพิ่มประสิทธิภาพการโหลด

โดยหลักการขั้นตอนการทำงานคือ

  • bundler วิเคราะห์ Dependency Graph จาก entry point และไล่ตาม import เพื่อทราบว่า file ใหนเชื่อต่อกัน อันใหนซ้ำ หรืออันใหนเป็น dynamic import
  • bundler จะ chunks ตามโครงสร้างที่รู้ล่วงหน้าอยู่แล้ว เช่นพวก entry points, routes (home page, about page) ส่วนนี้จะถูกเรียกว่า static splitting
  • ในขณะเดียวกัน ถ้า bundler เจอว่า code ส่วนใหนมีการ dynamic import ส่วนนี้จะถูก chunks แยกออกไป และ mark ไว้เพื่อให้ runtime เรียกใช้ภายหลัง
  • bundler จะสร้าง chuck graph ขึ้นมาใหม่เพื่อกำหนดว่าแต่ละ chunk มี module อะไรบ้าง
  • bundler จะรวม code ที่เรียกใช้ซ้ำๆกันไว้ใน vendor chunk เพื่อลดการซ้ำซ้อนน
  • ทำ optimization เพิ่มเติม (เช่น tree-shaking, deduplication)
  • สุดท้ายจะได้ chunk file และสร้าง manifest ออกมาเพื่อให้ runtime รู้ว่าต้องโหลดไฟล์ไหนเมื่อไหร่

Lazy Loading (Run time)

Lazy Loading คือเทคนิคการโหลดโค้ด (หรือ resource อื่น ๆ เช่น รูป, วิดีโอ, data) เฉพาะตอนที่ต้องใช้ แทนที่จะโหลดมาทั้งหมดตั้งแต่แรก
ในมุมของโค้ด JavaScript มันทำงานบนพื้นฐานของ Code Splitting ที่เกิดตอน Build Time แล้วไปโหลด chunk เหล่านั้นทีหลัง ตอน Runtime

โดยหลักการขั้นตอนการทำงานคือ

  • browser จะโหลด main bundle ที่เป็น static splitting มา
  • และถ้าหน้านั้นมีการเรียกใช้ lazy loading browser จะโหลด chunk เพิ่ม
  • ถ้าไม่พบ lazy loading browser ทำงานกับแค่ main bundle และ พวก vendor ที่โหลดมากับหน้า

ข้อดีของ process ทั้งสองตัวนี้

  • เหมาะกับโค้ดที่ใหญ่และไม่ได้ใช้ตั้งแต่โหลดหน้าแรก
  • ลดเวลาโหลด initial page
  • ประหยัด bandwidth

สรุป

โลกของ Frontend ไม่ได้วัดกันแค่ความสวยงามหรือฟีเจอร์แล้ว แต่ยังแข่งกันที่ความเร็วในการเข้าถึง และ UX ของผู้ใช้. Bundler ไม่ใช่เครื่องมือแปลงโค๊ดของ Frontend ให้ browser เข้าใจเท่านั้น แต่ยังคัดเลือก คัดสรรว่าไฟล์ที่ให้ browser นั้นควร serve ตอนใหนก่อนหรือหลัง ทำให้เราได้เว็บที่โหลดเร็วขึ้น ใช้ทรัพยากรน้อยลง และตอบสนองต่อผู้ใช้ได้ดี

sandwiched-developer-author
s
เขียนโดย

sirawich

[@portabletext/react] Unknown block type "undefined", specify a component for it in the `components.types` prop
อ่านต่อ

บทความที่เกี่ยวข้อง