เมื่อเราสร้างเว็บไซต์ที่อาศัย JavaScript มากขึ้น บางครั้งเราก็ต้องจ่ายค่าสิ่งที่ส่งไปในรูปแบบที่เราไม่สามารถมองเห็นได้ง่ายๆ ในบทความนี้ เราจะอธิบายว่าความมีระเบียบวินัยเล็กน้อยจะช่วยได้อย่างไรหากคุณต้องการให้เว็บไซต์โหลดและโต้ตอบได้อย่างรวดเร็วบนอุปกรณ์เคลื่อนที่ การส่ง JavaScript น้อยลงอาจทำให้เวลาในการรับส่งข้อมูลในเครือข่ายลดลง ใช้เวลาในการบีบอัดโค้ดน้อยลง และใช้เวลาในการแยกวิเคราะห์และคอมไพล์ JavaScript น้อยลง
เครือข่าย
เมื่อนักพัฒนาซอฟต์แวร์ส่วนใหญ่นึกถึงต้นทุนของ JavaScript ก็จะนึกถึงต้นทุนการดาวน์โหลดและการดำเนินการ ยิ่งการเชื่อมต่อของผู้ใช้ช้าลง การส่ง JavaScript ผ่านเครือข่ายก็จะใช้เวลานานขึ้น
ซึ่งอาจเป็นปัญหาได้ เนื่องจากประเภทการเชื่อมต่อเครือข่ายที่มีประสิทธิภาพที่ผู้ใช้มีอาจไม่ใช่ 3G, 4G หรือ Wi-Fi จริง คุณอาจใช้ Wi-Fi ของร้านกาแฟแต่เชื่อมต่อกับฮอตสปอตมือถือที่มีความเร็ว 2G
คุณลดต้นทุนการโอนเครือข่ายของ JavaScript ได้ดังนี้
- ส่งเฉพาะรหัสที่ผู้ใช้ต้องการ
- ใช้การแยกโค้ดเพื่อแบ่ง JavaScript ออกเป็นโค้ดที่สําคัญและไม่สําคัญ เครื่องมือรวมโมดูลอย่าง webpack รองรับการแยกโค้ด
- การโหลดโค้ดที่ไม่สําคัญแบบ Lazy Loading
- การลดขนาด
- ใช้ UglifyJS เพื่อลดขนาดโค้ด ES5
- ใช้ babel-minify หรือ uglify-es เพื่อลดขนาด ES2015 ขึ้นไป
- การบีบอัด
- การนำโค้ดที่ไม่ได้ใช้งานออก
- ระบุโอกาสในการนําโค้ดออกหรือโหลดแบบเลื่อนเวลาไว้ใช้กับการครอบคลุมโค้ดของเครื่องมือสําหรับนักพัฒนาเว็บ
- ใช้ babel-preset-env และ browserlist เพื่อหลีกเลี่ยงการแปลงโค้ดฟีเจอร์ที่มีอยู่แล้วในเบราว์เซอร์สมัยใหม่ นักพัฒนาซอฟต์แวร์ขั้นสูงอาจพบว่าการวิเคราะห์ webpack ของตัวเองอย่างละเอียดจะช่วยระบุโอกาสในการตัดการพึ่งพาที่ไม่จำเป็นออก
- สําหรับการลบโค้ด ให้ดูการแยกไฟล์ การเพิ่มประสิทธิภาพขั้นสูงของ Closure Compiler และปลั๊กอินการตัดแต่งไลบรารี เช่น lodash-babel-plugin หรือ ContextReplacementPlugin ของ webpack สําหรับไลบรารีอย่าง Moment.js
- การแคชโค้ดเพื่อลดการใช้งานเครือข่าย
- ใช้การแคช HTTP เพื่อให้แน่ใจว่าเบราว์เซอร์จะแคชการตอบกลับได้อย่างมีประสิทธิภาพ กำหนดอายุการใช้งานที่เหมาะสมสำหรับสคริปต์ (max-age) และระบุโทเค็นการตรวจสอบ (ETag) เพื่อหลีกเลี่ยงการโอนไบต์ที่ไม่มีการเปลี่ยนแปลง
- การแคช Service Worker ช่วยให้เครือข่ายแอปมีความยืดหยุ่นและให้คุณเข้าถึงฟีเจอร์ต่างๆ ได้อย่างรวดเร็ว เช่น แคชโค้ดของ V8
- ใช้การแคชระยะยาวเพื่อหลีกเลี่ยงการต้องดึงข้อมูลทรัพยากรที่ไม่ได้เปลี่ยนแปลงใหม่ หากใช้ Webpack โปรดดูการแฮชชื่อไฟล์
แยกวิเคราะห์/คอมไพล์
เมื่อดาวน์โหลดแล้ว ต้นทุนที่หนักที่สุดอย่างหนึ่งของ JavaScript คือเวลาที่เครื่องมือ JS ใช้ในการแยกวิเคราะห์/คอมไพล์โค้ดนี้ ใน Chrome DevTools การแยกวิเคราะห์และการคอมไพล์เป็นส่วนหนึ่งของเวลา "การเขียนสคริปต์" สีเหลืองในแผงประสิทธิภาพ
แท็บ Bottom-Up และ Call Tree จะแสดงเวลาในการแยกวิเคราะห์/คอมไพล์ที่แน่นอน

แต่เหตุใดเรื่องนี้จึงสำคัญ
การแยกวิเคราะห์/คอมไพล์โค้ดเป็นเวลานานอาจทำให้ผู้ใช้โต้ตอบกับเว็บไซต์ได้ช้าลงอย่างมาก ยิ่งคุณส่ง JavaScript มากเท่าใด ก็ยิ่งใช้เวลาในการแยกวิเคราะห์และคอมไพล์นานขึ้นเท่านั้นก่อนที่เว็บไซต์จะโต้ตอบได้
เมื่อพิจารณาแบบไบต์ต่อไบต์ เบราว์เซอร์จะประมวลผล JavaScript ได้ช้ากว่ารูปภาพหรือแบบอักษรเว็บที่มีขนาดเท่ากัน - Tom Dale
เมื่อเทียบกับ JavaScript นั้น รูปภาพขนาดเท่ากันมีต้นทุนการประมวลผลจำนวนมาก (ต้องถอดรหัสก่อน) แต่สำหรับฮาร์ดแวร์ในอุปกรณ์เคลื่อนที่ทั่วไป JS มีแนวโน้มที่จะส่งผลเสียต่อความสามารถในการโต้ตอบของหน้าเว็บมากกว่า

เมื่อพูดถึงการแยกวิเคราะห์และการคอมไพล์ที่ช้า บริบทก็มีความสำคัญ เนื่องจากเรากำลังพูดถึงโทรศัพท์มือถือทั่วไป ผู้ใช้ทั่วไปอาจมีโทรศัพท์ที่มี CPU และ GPU ที่ช้า ไม่มีแคช L2/L3 และอาจจํากัดหน่วยความจํา
ความสามารถของเครือข่ายและความสามารถของอุปกรณ์อาจไม่ตรงกันเสมอไป ผู้ใช้ที่มีการเชื่อมต่อไฟเบอร์ที่ยอดเยี่ยมไม่จำเป็นต้องมี CPU ที่ดีที่สุดในการแยกวิเคราะห์และประเมิน JavaScript ที่ส่งไปยังอุปกรณ์ ในทางกลับกัน การเชื่อมต่อเครือข่ายที่ช้ามากแต่มี CPU ที่เร็วสุดๆ ก็อาจทำให้ประสิทธิภาพลดลงเช่นกัน — Kristofer Baxter จาก LinkedIn
ด้านล่างนี้เราจะเห็นต้นทุนในการแยกวิเคราะห์ JavaScript (แบบง่าย) ที่ไม่มีการบีบอัดประมาณ 1 MB ในฮาร์ดแวร์ระดับต่ำและระดับสูง เวลาในการแยกวิเคราะห์/คอมไพล์โค้ดของโทรศัพท์ที่เร็วที่สุดในท้องตลาดกับโทรศัพท์ทั่วไปแตกต่างกัน 2-5 เท่า

แล้วเว็บไซต์ในชีวิตจริงอย่าง CNN.com ล่ะ
ใน iPhone 8 รุ่นไฮเอนด์ ใช้เวลาเพียงประมาณ 4 วินาทีในการแยกวิเคราะห์/คอมไพล์ JS ของ CNN เมื่อเทียบกับโทรศัพท์ทั่วไป (Moto G4) ที่ใช้เวลาประมาณ 13 วินาที ซึ่งอาจส่งผลอย่างมากต่อความเร็วที่ผู้ใช้โต้ตอบกับเว็บไซต์นี้ได้อย่างเต็มที่

ข้อมูลนี้แสดงให้เห็นถึงความสำคัญของการทดสอบบนฮาร์ดแวร์ทั่วไป (เช่น Moto G4) แทนที่จะทดสอบเฉพาะโทรศัพท์ที่คุณอาจพกติดตัวอยู่ บริบทมีความสำคัญ แต่อย่างไรก็ตาม โปรดเพิ่มประสิทธิภาพสำหรับอุปกรณ์และสภาพเครือข่ายของผู้ใช้

เราส่ง JavaScript มากเกินไปจริงหรือ อาจจะเป็นไปได้นะ :)
เมื่อใช้ HTTP Archive (เว็บไซต์ยอดนิยมประมาณ 500, 000 เว็บไซต์) เพื่อวิเคราะห์สถานะของ JavaScript บนอุปกรณ์เคลื่อนที่ เราพบว่าเว็บไซต์ 50% ใช้เวลานานกว่า 14 วินาทีในการโต้ตอบ เว็บไซต์เหล่านี้ใช้เวลาถึง 4 วินาทีในการแยกวิเคราะห์และคอมไพล์ JS
อย่าลืมคำนึงถึงเวลาในการดึงข้อมูลและประมวลผล JS และทรัพยากรอื่นๆ ด้วย จึงไม่น่าแปลกใจที่ผู้ใช้อาจต้องรอสักพักก่อนที่หน้าเว็บจะพร้อมใช้งาน เราปรับปรุงให้ดีกว่านี้ได้อย่างแน่นอน
การนำ JavaScript ที่ไม่สําคัญออกจากหน้าเว็บสามารถลดเวลาในการรับส่ง การแยกวิเคราะห์และการคอมไพล์ที่ต้องใช้ CPU มาก และลดการใช้หน่วยความจําที่อาจเกิดขึ้น วิธีนี้ยังช่วยให้หน้าเว็บโต้ตอบได้เร็วขึ้นด้วย
เวลาดำเนินการ
ไม่เพียงการแยกวิเคราะห์และการคอมไพล์เท่านั้นที่มีค่าใช้จ่าย การเรียกใช้ JavaScript (การเรียกใช้โค้ดเมื่อแยกวิเคราะห์/คอมไพล์แล้ว) เป็นหนึ่งในการดำเนินการที่ต้องเกิดขึ้นในเทรดหลัก เวลาที่ใช้ในการดำเนินการนานยังอาจทำให้ผู้ใช้โต้ตอบกับเว็บไซต์ได้ช้าลงด้วย
หากสคริปต์ทำงานนานกว่า 50 มิลลิวินาที เวลาในการตอบสนองจะล่าช้าตามเวลาที่ใช้ในการดาวน์โหลด คอมไพล์ และเรียกใช้ JS ทั้งหมด Alex Russell
ด้วยเหตุนี้ JavaScript จึงควรอยู่ในรูปแบบข้อมูลโค้ดขนาดเล็กเพื่อหลีกเลี่ยงการล็อกเทรดหลัก ตรวจสอบว่าคุณลดปริมาณงานที่ดำเนินการในระหว่างการดําเนินการได้หรือไม่
ค่าใช้จ่ายอื่นๆ
JavaScript อาจส่งผลต่อประสิทธิภาพของหน้าเว็บในลักษณะอื่นๆ ดังนี้
- ความทรงจำ หน้าเว็บอาจดูเหมือนกระตุกหรือหยุดชั่วคราวบ่อยครั้งเนื่องจาก GC (การเก็บขยะ) เมื่อเบราว์เซอร์เรียกคืนหน่วยความจำ การดำเนินการ JS จะหยุดชั่วคราว ดังนั้นเบราว์เซอร์ที่รวบรวมขยะบ่อยๆ จึงหยุดการดำเนินการบ่อยกว่าที่เราต้องการ หลีกเลี่ยงการรั่วไหลของหน่วยความจำและการหยุด gc บ่อยๆ เพื่อไม่ให้หน้าเว็บกระตุก
- ในระหว่างรันไทม์ JavaScript ที่ทำงานเป็นเวลานานอาจบล็อกเทรดหลัก ซึ่งส่งผลให้หน้าเว็บไม่ตอบสนอง การแบ่งงานออกเป็นชิ้นเล็กๆ (โดยใช้
requestAnimationFrame()
หรือrequestIdleCallback()
สำหรับการกําหนดเวลา) ช่วยลดปัญหาการตอบสนอง ซึ่งจะช่วยปรับปรุง Interaction to Next Paint (INP) ได้
รูปแบบการลดต้นทุนการแสดงผล JavaScript
เมื่อพยายามทำให้เวลาในการแยกวิเคราะห์/คอมไพล์และเวลาในการส่งผ่านเครือข่ายสําหรับ JavaScript ช้าลง ก็มีรูปแบบที่จะช่วยได้ เช่น การแบ่งกลุ่มตามเส้นทางหรือ PRPL
PRPL
PRPL (Push, Render, Pre-cache, Lazy-load) คือรูปแบบที่เพิ่มประสิทธิภาพเพื่อการโต้ตอบผ่านการแยกโค้ดและการแคชอย่างมีประสิทธิภาพ
มาดูภาพผลลัพธ์ที่อาจเกิดขึ้นกัน
เราวิเคราะห์เวลาในการโหลดของเว็บไซต์บนอุปกรณ์เคลื่อนที่และ Progressive Web App ยอดนิยมโดยใช้สถิติการเรียกใช้รันไทม์ของ V8 เราเห็นว่าเวลาในการแยกวิเคราะห์ (แสดงเป็นสีส้ม) เป็นส่วนสําคัญที่เว็บไซต์เหล่านี้ใช้เวลา
Wego เป็นเว็บไซต์ที่ใช้ PRPL ซึ่งรักษาเวลาในการแยกวิเคราะห์เส้นทางให้ต่ำได้ ทำให้โต้ตอบได้อย่างรวดเร็ว เว็บไซต์อื่นๆ อีกหลายแห่งข้างต้นใช้การแยกโค้ดและงบประมาณด้านประสิทธิภาพเพื่อพยายามลดต้นทุน JS
การเริ่มต้นแบบโปรเกรสซีฟ
เว็บไซต์จํานวนมากเพิ่มประสิทธิภาพการมองเห็นเนื้อหาโดยเสียค่าใช้จ่ายด้านความสามารถในการโต้ตอบ หากต้องการการแสดงผลครั้งแรกที่รวดเร็วเมื่อคุณมีกลุ่ม JavaScript ขนาดใหญ่ นักพัฒนาซอฟต์แวร์อาจใช้การแสดงผลฝั่งเซิร์ฟเวอร์ในบางครั้ง จากนั้น "อัปเกรด" เพื่อแนบตัวแฮนเดิลเหตุการณ์เมื่อมีการดึงข้อมูล JavaScript ในที่สุด
โปรดระมัดระวัง เนื่องจากการดำเนินการนี้อาจมีค่าใช้จ่าย 1) โดยทั่วไปแล้วคุณส่งการตอบกลับ HTML ที่ใหญ่ขึ้น ซึ่งอาจทำให้การโต้ตอบของเราลดลง 2) อาจทำให้ผู้ใช้รู้สึกอึดอัดเมื่อครึ่งหนึ่งของประสบการณ์ไม่สามารถโต้ตอบได้จนกว่า JavaScript จะประมวลผลเสร็จ
การเริ่มต้นแบบเป็นขั้นเป็นตอนอาจเป็นแนวทางที่ดีกว่า ส่งหน้าเว็บที่ใช้งานได้น้อยที่สุด (ประกอบด้วย HTML/JS/CSS ที่จําเป็นสําหรับเส้นทางปัจจุบันเท่านั้น) เมื่อทรัพยากรเข้ามามากขึ้น แอปจะโหลดแบบเลื่อนเวลาและปลดล็อกฟีเจอร์เพิ่มเติมได้

การโหลดโค้ดตามสัดส่วนกับสิ่งที่แสดงอยู่คือเป้าหมายสูงสุด PRPL และ Progressive Bootstrapping เป็นรูปแบบที่ช่วยให้บรรลุเป้าหมายนี้ได้
สรุป
ขนาดการส่งเป็นสิ่งสำคัญสำหรับเครือข่ายระดับล่าง เวลาแยกวิเคราะห์มีความสำคัญสำหรับอุปกรณ์ที่กําหนดโดย CPU การรักษาค่าเหล่านี้ให้ต่ำเป็นเรื่องสำคัญ
ทีมต่างๆ ประสบความสําเร็จเมื่อใช้งบประมาณด้านประสิทธิภาพที่เข้มงวดเพื่อรักษาเวลาในการส่งและแยกวิเคราะห์/คอมไพล์ JavaScript ให้ต่ำ ดู "Can You Afford It?: งบประมาณด้านประสิทธิภาพของเว็บในชีวิตจริง"เพื่อดูคําแนะนําเกี่ยวกับงบประมาณสําหรับอุปกรณ์เคลื่อนที่

หากคุณกำลังสร้างเว็บไซต์ที่กําหนดเป้าหมายเป็นอุปกรณ์เคลื่อนที่ ให้พยายามพัฒนาบนฮาร์ดแวร์ที่เป็นแบบอย่าง รักษาเวลาแยกวิเคราะห์/คอมไพล์ JavaScript ให้ต่ำ และนํางบประมาณด้านประสิทธิภาพมาใช้เพื่อให้ทีมของคุณควบคุมต้นทุน JavaScript ได้
ดูข้อมูลเพิ่มเติม
- Chrome Dev Summit 2017 - แนวทางปฏิบัติแนะนำในการโหลดแบบสมัยใหม่
- ประสิทธิภาพการเริ่มต้น JavaScript
- การแก้ปัญหาเกี่ยวกับประสิทธิภาพของเว็บ — Nolan Lawson
- คุณจ่ายไหวไหม งบประมาณด้านประสิทธิภาพจริง — Alex Russell
- การประเมินเฟรมเวิร์กและไลบรารีเว็บ - Kristofer Baxter
- ผลลัพธ์การทดสอบ Brotli ของ Cloudflare สำหรับการบีบอัด (โปรดทราบว่า Brotli แบบไดนามิกที่มีคุณภาพสูงขึ้นอาจทำให้การแสดงผลหน้าเว็บครั้งแรกล่าช้า ดังนั้นโปรดประเมินอย่างรอบคอบ คุณอาจต้องบีบอัดแบบคงที่แทน)
- Performance Futures — Sam Saccone