Chanto Logo
FRONTEND – 22 Jul 2018

5 เทคนิคการ Optimize เว็บ ให้เร็วขึ้นราวติดจรวด!!

Cover Image

ในปัจจุบัน Performance หรือความเร็ว มีความสำคัญมาก ๆ และส่งผลกระทบต่อโดยตรง ต่อประสบการณ์การใช้งานของผู้ใช้ และ Ranking ของ Google search

มีกรณีศึกษาจากเว็บดัง ๆ มากมาย ที่พูดถึงความสัมพันธ์ของความเร็ว กับผลกระทบที่เกิดขึ้น

โอ้โห ถ้าความเร็ว ส่งผลขนาดนี้ เราก็คงปล่อยให้เว็บเรา ช้ากว่าคู่แข่งไม่ได้แล้วล่ะครับ 😅

Optimize เว็บอย่างไรดี ?

การทำให้เว็บเร็วขึ้น มีอยู่สองแบบ คือ Optimize Objective time (เวลาที่วัดผลเป็นตัวเลขได้) หรือ Subjective time (เวลาที่มนุษย์รับรู้, ความรู้สึก)

บทความนี้ จะเป็นมุมมองของ Frontend Developer ผมจึงจะพูดถึงเทคนิคการ Optimize objective time ครับ เนื่องจากวัดผลได้ง่ายกว่า

เครื่องมือวัดผลแบบฟรี ที่แนะนำก็จะมี

ผมค่อนข้างชอบ GTMetrix มากกว่า เนื่องจาก Report มีความเจาะลึกในรายละเอียดมากกว่า ทำให้เรา “เกาที่คัน” ได้ง่ายกว่าครับ

เรามาดูกันว่า Frontend Developer ควรทำอะไรบ้างเพื่อให้เว็บเราเร็วขึ้นครับ

1.) Minify HTML, CSS, JS

การ Minify ทำได้ง่ายและควรทำเป็นอันดับต้น ๆ เรียกได้ว่าถ้าไม่นี่พลาดเลย โดยเป้าหมายของการ Minify คือการลดขนาด Resource ลง ส่งผลให้โหลด Resource เร็วขึ้น

กระบวนการ Minify จะทำการตัด Characters ที่ไม่จำเป็นออก เช่น Space หรือ Newline และถ้าตรวจสอบดูแล้วว่าปลอดภัย Minifier ก็จะทำการเปลี่ยนชื่อตัวแปลให้สั้นลงด้วย โดยที่ทุกอย่าง ยังคงทำงานเหมือนเดิม

Minify image ตัวอย่าง javascript ก่อน Minify (ซ้าย), หลัง Minify (ขวา)

การ Minify สามารถทำได้ง่าย โดยใช้ Plugin ของ Task runner หรือ Bundler เช่น Webpack, Gulp, Grunt หรือ Browserify โดยกรณีของผม คือทำการ Optimize Blog นี้ ผมจึงเลือกใช้ Gulp เพราะใช้งานง่าย สะดวกในการ Deploy และตรงความต้องการที่สุดครับ

Plugin ที่แนะนำคือ

2.) Optimize image

เป้าหมายของการ Optimize image คือทำรูปให้มีขนาดเล็กลง แต่คุณภาพของรูปเท่าเดิม หรือลดลงในระดับที่เหมาะสม

สิ่งที่ Frontend Developer ควรคำนึงมีดังต่อไปนี้

เลือก File type ให้เหมาะสมกับประเภทของภาพ

File type ทั่วไปที่ถูกใช้งานบ่อยคือ

ตัดข้อมูลที่ไม่จำเป็นต่อการแสดงผลออก

ในรูปภาพ จะมีข้อมูล Metadata ที่ไม่จำเป็นต่อการแสดงผล เช่น EXIF, Color profile, GPS, Gramma ซึ่งส่วนใหญ่เราไม่มีความจำเป็นที่ต้องใช้ เว้นแต่ในบางกรณี เช่นเรื่องของ Copyright เป็นต้น

สำหรับ MacOS เครื่องมือที่ผมใช้ในการลดขนาดภาพ คือ ImageOptim ที่ใช้งานได้ง่ายมาก แค่ Drag and Drop โปรแกรมก็จะทำการลดขนาดไฟล์ให้เราทันที โดยไม่ลดคุณภาพ แต่ก็สามารถตั้งค่าให้ลดคุณภาพลง เพื่อให้ขนาดเล็กลงอีกได้ครับ

ImageOptim ตัวอย่างการลดขนาดรูปด้วย ImageOptim

หลีกเลี่ยงการโหลดรูปขนาดใหญ่กว่าที่ใช้จริง

การส่งรูปที่ใหญ่กว่าที่ใช้งานจริง นอกจากที่จะโหลดช้าโดยไม่จำเป็นแล้ว ยังเปลือง Bandwidth อีกด้วย

โดยสาเหตุที่ผมเจอส่วนใหญ่ ก็มักจะมาจากเรื่องการแสดงผลบนจอ HiDPI เช่น Retina screen เลยส่งไฟล์ใหญ่สุดมาโดยไม่ Fallback สำหรับจอปรกติ ภาพจะได้คมชัด ลองคิดดูว่าถ้า มือถือต้องโหลดภาพที่ใช้กับจอ Retina มาแสดงผลนี่ เปลือง data มาก ๆ 😢

อีกส่วนคือมาจากการออกแบบที่ไม่ชัดเจน แยกความแตกต่างระหว่างส่วนที่เป็น Image และ Background Image ไม่ถูกต้อง ทำให้จำเป็นต้องใช้รูปที่มีขนาดไม่เหมาะสม

การทำ Responsive Image สามารถทำได้แบบง่ายที่สุดด้วย attribute srcset ของ <img> โดยที่เราสามารถกำหนดเงื่อนไข การเลือกใช้งานภาพใด ๆ ได้ทั้งแบบใช้เงือนไขตาม ความกว้างของหน้าจอ หรือ ตาม Resolution

srcset การใช้งาน srcset ตาม Resolution เพื่อโหลด ภาพ photo@2x.png เมื่อ device pixels มีขนาดเป็น 2 เท่าของ CSS pixels

HTML นี้จะเป็นการบอก Browser ว่า

จริง ๆ แล้วเรื่องการ Optimize Image นั้นยังมีเรื่องที่น่าสนใจอีกเยอะมาก เช่นการใช้ File type สมัยใหม่ เช่น WebP, JPEG2000 และการใช้ <picture> เพื่อแยก source เอาไว้ผมจะมาเล่นให้ฟังในบทความต่อ ๆ ไปครับ

3.) ลดความซับซ้อนของ DOM

เคยเห็น HTML ที่มี <div> ซ้อน <div> ซ้อน <div> … ไหมครับ ยิ่งเรา Nested HTML Tag ที่ไม่จำเป็นมากเท่าไร ก็ยิ่งมี node ที่ไม่จำเป็นมากขึ้น และ DOM Tree ของเราก็จะซับซ้อน ทำให้ Browser ใช้เวลามากขึ้นในการ Render

นอกจาก Browser แล้ว ก็ยังทำให้ Developer ด้วยกันเองนี่แหละครับ อ่าน Code ยากไปอีก

divitis การที่มี div มากเกินความจำเป็น (Divitis)

สาเหตุมาจากสองเรื่องคือ

  1. ในอดีตการทำ Layout มีความยาก – ในยุคก่อน ๆ Layout บางรูปแบบ ทำยากมาก และยังต้องรองรับ Responsive อีกด้วย การใส่ container ที่ไม่จำเป็นจึงเกิดขึ้นมาเพื่อ hack ให้ได้ layout ที่ต้องการ แต่ในปัจจุบัน หลังจากที่มี Flexbox และ CSS Grid การ hack เหล่านั้น ก็ไม่จำเป็นอีกต่อไปแล้ว

  2. CSS Framework สร้างมาตรฐานที่ไม่ดีเอาไว้ – ใครที่เคยเข้าไป Copy snippet code ของ CSS framework ชื่อดังบางตัว คงจะคุ้นตากับ Markup ที่มี div ซ้อนกันเยอะมาก ๆ ใช่ไหมครับ (ไม่รู้ว่าปัจจุบัน ดีขึ้นหรือยัง)

bootstrap snippet code ของ bootstrap (นี่ขนาดยังไม่ได้ใส่ Responsive container เข้าไปนะนี่)

การเขียน HTML สมัยใหม่จึงควร ลด ละ เลิก การเขียนที่มีความซับซ้อนโดยไม่จำเป็นครับ

4.) CSSOM เรื่องที่ไม่ควรมองข้าม

การใส่ class ที่ไม่ได้ใช้งานมาใน CSS ไม่เพียงแต่จะทำให้ขนาดไฟล์ ใหญ่เกินความจำเป็น แต่ class เหล่านั้น ยังต้องถูกนำมาสร้างเป็น CSSOM (CSS Object Model) ด้วย ถึงแม้ใน Document เราจะไม่ได้ใช้งาน class เหล่านั้นก็ตาม 😱

แม้ว่าเราจะ cache CSS ไฟล์ได้ แต่ CSSOM จะไม่ถูก cache ไปด้วย และ Web browser จะสร้าง CSSOM ขึ้นมาใหม่ทุกครั้งที่เราโหลดหน้า

CSSOM จะถูกนำมารวมกับ DOM เพื่อใช้สร้าง Render Tree ในตอนหลัง จึงทำให้ทั้ง HTML (ใช้สร้าง DOM) และ CSS (ใช้สร้าง CSSOM) เป็น Resource ที่ Render Blocking

render-tree DOM, CSSOM และ Render Tree

การลบ class ที่ไม่ได้ใช้งานออกไป เราสามารถใช้เครื่องมือ อย่าง เช่น PurgeCSS เพื่อ Automate จัดการให้เราได้

PurgeCSS ก็มีเป็น Plugin ใช้ได้กับทุก Task runner หรือ Bundler tool เลยครับ สะดวกมาก

PurgeCSS จะทำการตรวจสอบ content ที่เราระบุ เช่น html, md, tmpl และ เทียบกับ CSS selector ใน CSS ไฟล์ และลบ class ที่ไม่ได้ถูกใช้งานออก

ซึ่งผมรับประกันว่าคุณจะต้องตกใจ กับขนาดที่ลดลงไปของ CSS ไฟล์แน่นอน โดยเฉพาะ CSS ของ Framework ใหญ่ ๆ หรือ Framework แนว Atomic ที่เราใช้งาน Class แค่บางส่วนเท่านั้น

ตัวอย่างเช่น chanto.io ใช้ biomatic-ui ที่เป็น Atomic CSS ก็สามารถลดขนาด CSS ไฟล์ลง จาก 243 kB เหลือเพียง 8 kB (ยังไม่ gzip) ลดลงไปถึง 97% 🤩

5.) ทำ Resource Hints

Resource Hints ใช้เพื่อบอกใบ้ ให้ Browser ให้ทำการโหลด หรือติดต่อไปยัง Resource ใด ๆ ล่วงหน้า เพราะเราจะใช้งาน Resource นั้นในอนาคตอันใกล้ โดยที่ไม่ Block onload event ของ window

สามารถใช้กับ Resource ได้ทั้ง JS, CSS, font, image, audio, video และอื่น ๆ อีกมากมาย เรียกได้ว่า เราสามารถทำ Resource Hints ได้กับ Resource แทบทุกอย่างเลย

สำหรับ Resource Hints ที่ใช้ในการ Navigate หน้าปัจจุบัน ที่สำคัญและใช้งานบ่อย คือ preload และ dns-prefetch

preload การบอกให้ Browser ทำการ preload style.css ล่วงหน้า

dns-prefetch การบอกให้ Browser ทำการ DNS lookup domain cdnjs.cloudflare.com ล่วงหน้า

สุดท้าย

การ Optimize web performance ยังมีสิ่งที่ต้องทำอีกมากมาย เป็นงานที่ไม่มีวันจบ เพราะ Web Browser มีการพัฒนาอยู่ตลอด เราจึงต้องศึกษา และใช้งานมันให้เต็มประสิทธิภาพที่สุด

นอกจากนี้ยังมีเรื่องเล็ก ๆ น้อยที่ไม่ควรละเลยอยู่อีก เช่น

สุดท้ายคือ เราไม่จำเป็นต้องมุ่งหวังทำ Perfect Score ก็ได้ เพราะเราไม่อาจควบคุมปัจจัยภายนอก และบางอย่างมันก็อาจจะไม่่ Make sense ในระบบของเราครับ