เว็บช้าใครจะอยากเข้า – 6 เทคนิคเร่งสปีดให้เว็บโหลดเร็วปรู๊ด
เรื่องความเร็วในการโหลดเว็บนั้นเป็นเรื่องที่มองข้ามกันไม่ได้เลย ล่าสุดเมื่อกุมภาพันธ์ที่ผ่านมา Google ประกาศอย่างเป็นทางการว่าได้นำความเร็วในการโหลดเว็บมาเป็นปัจจัยในการจัดอันดับผลการค้นหาจากมือถือ และ Google ก็ยังพบว่าผู้ใช้งานกว่า 53% จะปิดเว็บที่โหลดไม่เสร็จภายใน 3 วินาที มาลองดูกันว่ามีเทคนิคไหนบ้างที่ทำให้เว็บของเราโหลดได้เร็วยิ่งขึ้น
การเตรียมตัว: วัดผลก่อนเริ่ม
ก่อนที่จะเริ่ม optimize เราควรจะมีเครื่องมือในการวัดผลเพื่อให้มั่นใจว่าสิ่งที่ทำไปดีขึ้นจริงๆ โดยเราขอแนะนำเครื่องมือ 2 ตัวนี้
Google PageSpeed Insight
เครื่องมือตัวแรกคือ PageSpeed Insight ซึ่งสามารถใช้งานได้ฟรีที่ https://developers.google.com/speed/pagespeed/insights/ โดยกรอก URL ของเว็บเราลงไป โปรแกรมก็จะแสดงผลว่าเว็บไซต์ของเราเร็วขนาดไหน และปรับปรุงอย่างไรได้บ้าง
Lighthouse
โปรแกรม Lighthouse เป็นส่วนขยายของ Google Chrome ซึ่งดาวน์โหลดได้จาก Chrome Web Store วิธีใช้แค่เพียงเปิด Developer Tools ขึ้นมา เลือกแท็บ Audit แล้วกด Perform an audit
โปรแกรมจะมีการวัดผลและแสดงคำแนะนำต่างๆ ออกมาให้เราแก้ไขต่อไป
เมื่อเรารู้ผลก่อนปรับปรุงแล้ว ลองมาดูกันว่ามีวิธีไหนบ้างที่ช่วยให้เว็บของเราเร็วขึ้น
1. ย้าย <script> ลงด้านล่าง
เทคนิคแรกของเรามีที่มาจากว่า เมื่อ Browser พบ tag <script> นั้น Browser จะต้องโหลดและประมวลผล JavaScript ให้เสร็จก่อน จึงจะทำงานต่อไปได้ แม้เนื้อหาของเว็บโหลดเสร็จแล้วก็ต้องหยุดรอก่อน ทำให้คนเข้าเว็บของเราต้องนั่งจ้องหน้าจอขาวๆ
วิธีการเลี่ยงง่ายๆ คือนำ <script> ไปไว้ด้านล่างสุดก่อนปิด </body> เพื่อให้โหลดเนื้อหาของเว็บให้เสร็จเป็นอย่างแรก
อีกวิธีหนึ่งนอกจากการย้าย tag ลงมาคือเปลี่ยน tag เป็น <script defer> ซึ่งจะทำให้ browser รับรู้ว่าต้องโหลดไฟล์นั้น แต่ยังไม่เรียกให้ script ทำงานจนกว่าหน้าจะโหลดเสร็จ เรียกได้ว่าไม่ทำให้เว็บโหลดช้าลง แถมยังโหลดรอระหว่างโหลดหน้าเว็บได้อีกด้วย
ทั้งนี้ทั้งนั้นโค้ดที่มีอยู่แล้วอาจจะไม่รองรับการใช้กับ <script defer> ควรทดสอบก่อนนำไปใช้
2. เลือกขนาดภาพให้เหมาะกับการใช้งาน และบีบอัดรูปให้สุด
เมื่อเราจะต้องใส่ภาพต่างๆ บนหน้าเว็บนั้นควรจะใช้ไฟล์ภาพที่มีขนาดเหมาะสมกับจุดที่แสดงผล เช่นถ้าหากจุดที่แสดงผลขนาด 300x200px แต่ภาพนั้นขนาด 1200x800px ก็จะทำให้ browser ต้องโหลดภาพขนาดใหญ่มาโดยไม่จำเป็น (เรียกง่ายๆ ว่าเปลือง 3G) ฉะนั้นแล้วเวลานำรูปเข้ามาใช้ควรจะ Crop หรือ Resize ให้ตรงกับขนาดที่ใช้งานจริงเสมอ
สำหรับเว็บไซต์ที่ต้องรองรับผู้ใช้มือถือนั้น อาจจะจำเป็นต้องใช้ภาพความละเอียดสูงเพื่อให้ภาพไม่แตก เราอาจจะใช้ tag <picture> หรือ <img srcset> แล้วเตรียมรูปไว้หลายๆ ขนาด เพื่อให้ Browser เลือกโหลดขนาดที่เหมาะสมกับหน้าจอที่ใช้ ทั้งนี้ควรตรวจสอบก่อนใช้งานว่ากลุ่มผู้ใช้งานของเรานั้นใช้ Browser ที่รองรับ tag ดังกล่าว หากไม่รองรับอาจจะต้องใช้ JavaScript library เช่น picturefill เข้ามาช่วย
รูปแบบของไฟล์ภาพและการบีบอัดก็มีผลเช่นเดียวกัน โดยภาพนามสกุล PNG นั้นจะรักษาคุณภาพไว้ตามต้นฉบับ 100% แต่บางครั้งอาจจะทำให้ภาพมีขนาดใหญ่ โดยเฉพาะเมื่อใช้กับภาพถ่าย หากเรายอมลดคุณภาพบางส่วนได้อาจจะเลือกใช้ภาพแบบ JPG แทน ซึ่งจะได้ภาพที่มีขนาดเล็กกว่ามาก
สุดท้ายนี้ เรายังสามารถบีบอัดภาพให้เล็กลงได้อีกโดยใช้โปรแกรม ImageOptim บน Mac, FileOptimizer บน Windows หรือ Trimage บน Linux ซึ่งจะใช้เทคนิคต่างๆ บีบอัดภาพลงไปอีกโดยไม่เสียคุณภาพ แต่จะใช้เวลาหลายนาทีสำหรับภาพใหญ่
3. บีบอัดข้อมูลอยู่เป็นนิจ
นอกจากรูปแล้ว เรายังสามารถบีบอัดข้อมูลต่างๆ ได้ด้วยโดยใช้ Algorithm gzip ซึ่ง web server หลายๆ ตัวสามารถทำให้เราได้โดยอัตโนมัติ เช่นใน nginx สั่ง gzip on; หรือใน Web framework หลายๆ เจ้ามักจะมี middleware ที่บีบ gzip ให้เราโดยอัตโนมัติ เช่น compression ของ express, GZipMiddleware ของ Django
สำหรับไฟล์บางประเภทที่เราเตรียมไว้ล่วงหน้า เราอาจจะบีบ gzip ที่อัตราบีบอัดสูงๆ ไว้เลยเพื่อความรวดเร็ว เช่นใช้ ZopfliWebpackPlugin และ BrotliWebpackPlugin สำหรับ Webpack โดยมีข้อแตกต่างกันดังนี้
- อัลกอริธึม Zopfli รองรับทุก browser แต่ใช้เวลานานกว่า gzip ปกติ (ได้ผลลัพท์เป็น .gz)
- อัลกอริธึม Brotli ต้องใช้ Browser ที่รองรับเท่านั้น (ได้ผลลัพท์เป็น .br)
- สามารถเตรียมไฟล์ไว้ทั้ง 2 แบบได้เพื่อให้รองรับทุก browser
โดยเราจะต้องตั้งค่า web server ให้ส่งไฟล์ .gz และ .br ที่เตรียมไว้ล่วงหน้า เช่นใช้ express-static-gzip หรือ Caddy web server ซึ่งจะเช็คว่า Browser นั้นรองรับไฟล์รูปแบบใด แล้วส่งไฟล์ที่เตรียมไว้แล้วให้
การบีบอัดไฟล์นั้นช่วยลดขนาดไฟล์ได้สูงสุดถึง 80% ทั้งนี้ไฟล์บางประเภทอาจมีการบีบอัดไว้แล้ว การเพิ่ม gzip เข้าไปก็จะไม่ช่วยให้บีบอัดได้ดีขึ้น เช่นไฟล์สื่อต่างๆ jpg, png, mp3, mp4 หรือไฟล์บีบอัดทั่วไป zip, rar ก็อาจจะเลือกเปิด gzip เฉพาะไฟล์ที่จำเป็น เช่นไฟล์ .html, .css, .js, .svg เพื่อลดภาระของ server
4. ใช้ HTTP/2 เพิ่มท่อส่งขนาน
ปัจจุบัน Browser และ Web server จำนวนมากรองรับ HTTP/2 แล้ว จึงควรปรับเว็บไซต์ของเราให้ใช้ HTTPS และ HTTP/2 ได้ (HTTP/2 ไม่รองรับเว็บไซต์ที่เป็น HTTP ไม่เข้ารหัส)
ข้อดีของการใช้ HTTP/2 คือสามารถโหลดข้อมูลคู่ขนานกันได้มากขึ้น สามารถลองดูตัวอย่างได้ที่ https://http2.akamai.com/demo ซึ่งจะเห็นว่า HTTP/2 โหลดได้เร็วกว่า HTTP/1.1 แบบเดิมอย่างเห็นได้ชัด
สำหรับการใช้ HTTP/2 นั้นจะต้องปรับ web server ที่อยู่ด้านหน้าสุดเท่านั้น เช่นถ้าหากแอพของเราเป็น Node.js แล้วมี nginx อยู่ด้านหน้าอีกทีหนึ่ง ให้ปรับที่ nginx เท่านั้น ไม่จำเป็นต้องปรับที่ Node.js โดยใน nginx config ให้ระบุบรรทัด listen ว่า listen 443 ssl http2; แล้ว reload
สำหรับ web server อื่นๆ นั้นขณะนี้ Web server เจ้าตลาดทุกเจ้า ไม่ว่าจะเป็น Apache, IIS, AWS ALB หรือ Google Cloud L7 Load Balancer ก็รองรับกันทั้งสิ้น ซึ่งอาจจะต้องเข้าไปเปิดใช้งาน รวมถึงเซตเว็บให้เป็น HTTPS ก่อนจึงจะใช้งานได้
5. ใช้ Client Caching ให้ browser ช่วยเรา
“รบร้อยครั้งชนะร้อยครั้ง” ก็ไม่เลิศเท่า “ชนะโดยไม่ต้องรบ” เช่นเดียวกัน ถ้าเราไม่จำเป็นต้องโหลดข้อมูลซ้ำเลยย่อมทำให้เว็บของเราโหลดได้เร็วขึ้น วิธีการก็คือเราจะต้องบอกให้ Browser ของผู้ใช้งานทราบว่าข้อมูลนี้สามารถเก็บไว้ในเครื่องได้โดยไม่ต้องโหลดซ้ำ
อะไรที่สามารถ Cache ได้
โดยทั่วไปแล้วในหน้าเว็บจะมีของหลายๆ อย่างที่สามารถ cache ไว้ได้ เช่น
- ไฟล์โค้ด JavaScript, CSS
- ไฟล์รูปภาพต่างๆ
- ถ้าหากหน้าเว็บของเรามั่นใจว่าจะไม่มีการเปลี่ยนแปลง ก็สามารถแคชไว้ทั้งหน้าได้เช่นเดียวกัน
เริ่มแคชอย่างไร
การอนุญาตให้ Browser Cache ได้นั้นถูกควบคุมโดย Header 2 ตัว ได้แก่
- Expires: กำหนดวันที่และเวลาที่หมดอายุแคช ระบุเป็นวันที่ เช่น Mon, 31 Dec 2018 07:00:00 GMT และหากเราระบุเป็นวันที่ในอดีตจะทำให้ Browser ไม่แคชไว้เลย
- Cache-Control: กำหนดเงื่อนไขการแคชต่างๆ โดยปกติแล้วเราจะใส่ว่า public, max-age=3153600 แปลว่าข้อมูลนี้เป็นสาธารณะ (ไม่มีข้อมูลส่วนตัวของผู้ใช้) อนุญาตให้แคชได้เป็นเวลา 3,153,600 วินาที หรือ 365 วัน นับจากเวลาที่ได้รับข้อมูล ถ้าหากต้องการให้เวลามากน้อยกว่านี้ก็สามารถปรับเปลี่ยนได้ตามต้องการ
โดยเราจะต้องส่ง header ออกมาพร้อมกับเนื้อหาในเว็บของเรา หากมีทั้ง 2 ตัว Browser จะอ้างอิงจาก Cache-Control เป็นหลัก
ตัวอย่างการ cache เช่นใน express สามารถใช้คำสั่ง
app.get('/', function(req, res){
res.set('Cache-Control', 'public,max-age=3153600');
res.end('Hello world');
});
นอกจากนี้ Web framework หลายๆ ตัวก็จะมีตัวช่วยในการตั้งค่า cache ด้วย เช่น @cache_control decorator ใน Django
เทคนิคในการแคช
บางครั้งเราอาจจะจำเป็นต้องอัพเดตเนื้อหาที่ cache ไว้ เช่นอัพเดต JavaScript ใหม่ วิธีที่ควรทำคือการตั้ง URL ให้อ้างอิงกับเนื้อหา เช่นรูปหมวดก๋วยเตี๋ยวของวงในอยู่ที่ https://www.wongnai.com/static/5.52.0/category/common/images/color/30.png เมื่อเราออกเวอร์ชั่นใหม่เลขเวอร์ชั่นใน URL จะเปลี่ยนไป ทำให้ user ต้องดาวน์โหลดภาพใหม่
อีกรูปแบบหนึ่งที่นิยมใช้กันคือการเติมแฮชของไฟล์ต่อท้ายชื่อไฟล์ ซึ่งเครื่องมือหลายๆ ตัวสามารถช่วยเราได้ เช่นการระบุ [chunkhash] ในชื่อไฟล์ของ Webpack หรือการใช้ ManifestStaticFilesStorage ใน Django โดยเราจะได้ URL ในที่มีข้อความสุ่ม (ตามเนื้อหาของไฟล์) ต่อท้าย เช่น https://www.wongnai.com/static2/mainb5a7c4980ab5128b9d16.css เมื่อมีการแก้ไขเนื้อหาภายในไฟล์ เครื่องมือก็จะอัพเดตข้อความสุ่มนั้นให้เปลี่ยนไปโดยอัตโนมัติ
6. ใช้ CDN ทำให้เรา “ใกล้กันมากขึ้น”
ในบางครั้ง server ของเราอาจจะอยู่ต่างประเทศ เช่นอยู่บน AWS หรือ Google Cloud ซึ่งทำให้ผู้ใช้ที่อยู่ในประเทศไทยนั้นเข้าได้ช้าลงกว่าเว็บไซต์ภายในประเทศ จึงมีบริการประเภท CDN ที่ให้บริการเซิร์ฟเวอร์ภายในประเทศไทย และเมืองอื่นๆ ทั่วโลก โดยจะช่วยเราดังต่อไปนี้
- พักไฟล์ที่อนุญาตให้แคชได้ไว้ใน server เพื่อให้เมื่อมีผู้ใช้งานหลายๆ คนเข้ามาสามารถโหลดไฟล์ได้จากภายในประเทศ
- หากไฟล์นั้นไม่สามารถแคชได้ CDN จะโหลดจาก server ต้นทางของเราให้ โดยเลือกใช้เส้นทางที่เหมาะสม ซึ่งอาจมีผลดีเมื่อผู้ให้บริการอินเทอร์เน็ตของผู้ใช้งานออกต่างประเทศได้ไม่ดีนัก
- กรองข้อมูลที่จะเข้าสู่ server ของเราเพื่อป้องกันการยิง DDoS
สำหรับผู้ให้บริการ CDN ที่มีเครื่องเซิร์ฟเวอร์ภายในประเทศไทย เว็บไซต์ CDNPlanet ได้ระบุไว้จำนวน 7 บริษัท ดังนี้
- CDN77
- CDNetworks
- CacheFly
- * CloudFlare
- * Limelight
- QUANTIL
- SwiftServe
- * นอกจากนี้ Akamai ก็มีเซิร์ฟเวอร์ตามหัวเมืองในประเทศไทยด้วย
ผู้ให้บริการที่มีเครื่องหมาย * คืออยู่ในโครงการ Google Cloud CDN Interconnect ซึ่งหากระบบของเราอยู่บน Google Cloud จะเสียค่า data transfer เพียงครึ่งเดียว
โดยเจ้าที่เราจะสามารถสมัครด้วยตัวเอง และเริ่มใช้งานได้เลยจะมี CDN77 และ CloudFlare ซึ่งเจ้าหลังนี้สามารถเริ่มใช้งานได้ฟรีอีกด้วย
สำหรับเว็บไซต์เล็กๆ อาจจะมองว่าค่าบริการ CDN ค่อนข้างสูง แต่เมื่อเว็บไซต์มีผู้ใช้เพิ่มขึ้นจะพบว่า CDN นั้นช่วยลดโหลดของ server เรา ทำให้เราเสียค่า server และ data transfer ออกจาก cloud ที่เราใช้ลดลง โดยวงในพบว่าการใช้ CloudFlare บน server รูปภาพของเรานั้นลดค่าใช้จ่ายได้ถึงเกือบ 40% เรียกได้ว่านอกจากจะเร็วแล้วยังถูกกว่าอีกด้วย
เปรียบเทียบผล
หลังจากปรับปรุงเว็บแล้ว อย่าลืมวัดผลอีกครั้งด้วย Google PageSpeed Insight หรือ Lighthouse เพื่อยึนยันได้ว่าสิ่งที่เราทำไปได้ผลจริงๆ
สำหรับ 6 เทคนิคด้านบนนี้เป็นเทคนิคพื้นฐานที่ช่วยให้เว็บทำงานได้เร็วขึ้น นอกไปเทคนิคเหล่านี้แล้วความเร็วของ server ของเรายังมีผลมากอีกด้วย ซึ่งก็จะเป็นเทคนิคเฉพาะตัวของแต่ละภาษา และ framework ที่ใช้กันไป
บทความโดย: มนัสวิน หาญมงคลชัย | Junior Architect @ wongnai.com
รูปประกอบบทความ: https://www.pexels.com/photo/black-and-white-nascar-car-39619/