ไม่ว่าเราจะพัฒนาเว็บแอพพลิเคชันด้วยเฟรมเวิร์คอะไรก็ตาม เมื่อนำไป deploy ในสภาวะแวดล้อมจริง เราควรจะมั่นใจว่าเราได้ optimize ขนาดของ JavaScript และ CSS ให้เหมาะกับการใช้งาน ซึ่งโดยบ่อยครั้งที่ผมเจอก็จะเป็นปัญหาขนาดของ JavaScript ที่มีขนาดใหญ่ ทำให้เวลาที่เสียเวลาตอนโหลด และอาจจะสร้างประสบการณ์ที่ไม่ดีแก่ผู้ใช้งาน
สำหรับ Rails ซึ่งที่ใช้ Webpack ในการคอมไฟล์และบีบอัดไฟล์ จะมี plugin ที่ใช้สำหรับการวิเคราะห์ว่าในไฟล์ js ที่ได้มัดรวม (bundle) เข้าด้วยกันนั้นประกอบไปด้วย js อะไรบ้าง และมีขนาดเท่าไหร่บ้าง
สำหรับเจ้าตัว plugin ที่ใช้แสดง visualize ข้างต้นก็คือ`webpack-bundle-analyzer` เพียงแค่เราติดตั้ง และรันตามคำสั่งข้างล่าง
สำหรับ Rails ซึ่งที่ใช้ Webpack ในการคอมไฟล์และบีบอัดไฟล์ จะมี plugin ที่ใช้สำหรับการวิเคราะห์ว่าในไฟล์ js ที่ได้มัดรวม (bundle) เข้าด้วยกันนั้นประกอบไปด้วย js อะไรบ้าง และมีขนาดเท่าไหร่บ้าง
สำหรับเจ้าตัว plugin ที่ใช้แสดง visualize ข้างต้นก็คือ`webpack-bundle-analyzer` เพียงแค่เราติดตั้ง และรันตามคำสั่งข้างล่าง
$(yarn bin)/webpack --config config/webpack/production.js --profile --json > stats.json $(yarn bin)/webpack-bundle-analyzer stats.json
จะขอยกตัวอย่างไฟล์ js จากแอพพลิเคชันที่ผมและทีมได้พัฒนาขึ้นมาดังแสดงในภาพข้างต้น พบว่ามีขนาดรวมทั้งหมด 673.84KB ซึ่งประกอบไปด้วย js ต่างๆ ด้วยกันหลายตัว แต่ที่ดูแล้วมีขนาดใหญ่ ก็จะมีด้วยกัน 3 ตัวคือ
- trix.js ขนาด 323.3KB
- bootstrap.esm.js ขนาด 208.26KB
- sweetalert2.all.js ขนาด 140.03KB
เมื่อลงลึกถึงขนาดนี้แล้ว ก็ถึงคราวที่ต้องพิจารณาต่ออีกว่า เรามีความจำเป็นต้องใช้ js ดังกล่าวหรือไม่ หรือมี js ตัวไหนที่ขนาดเล็กกว่าและนำมาทดแทนได้บ้าง
เริ่มต้นจาก trix.js ซึ่งเป็น lib สำหรับจัดการ rich text ซึ่งมีความจำเป็นต้องใช้งาน แต่ว่าไม่จำเป็นจะต้องโหลดทันที และไม่ได้มีการใช้ rich text เฉพาะบางหน้าเท่านั้น ดังนั้น lib ตัวนี้สามารถแยกออกจาก js หลัก และให้โหลดเมื่อต้องการใช้งานเท่านั้นได้ หรือที่เรียกว่า Lazy Loading
ถัดมาจากโจทย์แอพพลิเคชันตัวนี้ กำหนดให้ทดลองใช้ Bootstrap 5 ดังนั้น bootstrap.esm.js จึงไม่สามารถตัดออกไปได้แน่ๆ เพราะอาจจะทำให้คอมโพเนนต์บางตัวไม่สามารถทำงานได้
และสุดท้ายคือ sweetalert2.all.js ซึ่ง lib อันนี้ถือว่าไม่ได้สำคัญมาก สามารถตัดออกไปได้ แต่เพื่อความสวยงามเลยเก็บไว้ก่อน ไว้มีเวลาค่อยดูอีกทีว่ามี lib ตัวไหนที่ขนาดเล็กกว่า และเอามาแทนที่ได้
ทั้งนี้เราจะได้ bundle ใหม่ที่ใช้เป็น 2 ไฟล์ด้วยกันคือ
เริ่มต้นจาก trix.js ซึ่งเป็น lib สำหรับจัดการ rich text ซึ่งมีความจำเป็นต้องใช้งาน แต่ว่าไม่จำเป็นจะต้องโหลดทันที และไม่ได้มีการใช้ rich text เฉพาะบางหน้าเท่านั้น ดังนั้น lib ตัวนี้สามารถแยกออกจาก js หลัก และให้โหลดเมื่อต้องการใช้งานเท่านั้นได้ หรือที่เรียกว่า Lazy Loading
ถัดมาจากโจทย์แอพพลิเคชันตัวนี้ กำหนดให้ทดลองใช้ Bootstrap 5 ดังนั้น bootstrap.esm.js จึงไม่สามารถตัดออกไปได้แน่ๆ เพราะอาจจะทำให้คอมโพเนนต์บางตัวไม่สามารถทำงานได้
และสุดท้ายคือ sweetalert2.all.js ซึ่ง lib อันนี้ถือว่าไม่ได้สำคัญมาก สามารถตัดออกไปได้ แต่เพื่อความสวยงามเลยเก็บไว้ก่อน ไว้มีเวลาค่อยดูอีกทีว่ามี lib ตัวไหนที่ขนาดเล็กกว่า และเอามาแทนที่ได้
ทั้งนี้เราจะได้ bundle ใหม่ที่ใช้เป็น 2 ไฟล์ด้วยกันคือ
- application.js ขนาด 43219KB ซึ่งเป็น js หลักที่ถูกโหลดขึ้นมา
- rich_text.js ขนาด 247.38KB ซึ่งจะโหลดเฉพาะหน้าที่มีการเรียกใช้งาน trix.js เท่านั้น
สรุปกันสักหน่อย
- สำหรับผู้ที่ใช้ webpack เราสามารถใช้ plugin `webpack-bundle-analyzer` เพื่อตรวจสอบดูว่า lib ตัวไหนที่ทำให้ bundle ของเราบวมได้
- ถ้าอยากให้ขนาดของ js มีขนาดเล็กก็พยายามเลือก CSS ที่ไม่ผูกกับ JS มาได้อย่างเช่น Bulma หรือ Tailwind
- จริงอยู่ที่เราควรจะลดขนาดของ js ให้เล็กที่สุดเท่าที่จะทำได้ แต่ถ้าเราลดขนาดไม่จริงๆ ก็อาจจะพิจารณา flow ดูว่า js ตัวไหนที่ไม่จำเป็นต้องโหลดทันที (Eager Loading) และเลือกที่จะโหลดเมื่อต้องการใช้งานได้บ้าง (Lazy Loading)