Opportunity Cost ของการสร้าง Web Blog

Written by
SaltyAom's profile image
SaltyAom
On 1 Feb 2021
Opportunity Cost ของการสร้าง Web Blog
ภาพประกอบของเกม Blue Archive

หลังจากสร้าง web blog ใหม่มาจนไม่นับแล้ว ในที่สุดก็ตั้งใจว่าจะสร้าง blog ที่ maintain ง่ายๆ และ performance ดีๆ ขึ้นมาซักอันไว้ใช้ ขึ้นด้วยความขี้เกียจที่จะทำใหม่แล้ว

ด้วยความที่เป็นคนขี้เกียจ บางเวลาไม่ได้เขียนอะไรนานๆ ก็ลืม พอมาจับใหม่ก็ต้องมานั่งอ่านใหม่แต่แรก เลยอยากเขียนสรุปอันนึงเอาไว้ใช้อ่านเอง แต่ว่าไหนๆ ก็เขียนสรุปขึ้นมาแล้วก็เขียนเป็น blog เผื่อเอาไว้เลยละกัน

พอจะสร้างเว็บ ปัญหาก็คือ เว็บทุกวันนี้โดน over-engineer จนมีขนาดใหญ่มากเกินไปมากๆ ในส่วนของ Frontend

ปัญหาของเว็บในปัจจุบัน

ด้วยความสงสัยก็เลยอยากรู้ว่าเว็บ blog อันนึงจะมีขนาดได้เล็กซักแค่ไหน ก็เลยอยากลองเล่าปัญหาขึ้นมาก่อนว่า ทุกวันนี้มันเกิดจากอะไร

เว็บทุกวันนี้มีขนาดใหญ่มาก ที่เกิดจากการ over-engineer และใช้ library ผิด case

เช่นหน้า Landing บางเว็บที่เป็นหน้า static เปล่าๆ แต่กลับใช้ Angular ที่มีขนาดใหญ่มากในการทำ ทำให้ต้องโหลด JavaScript มาเสียฟรีๆ เพื่อเพิ่ม functionality บางอย่างเช่น Material Button

ไม่ใช่ว่า Angular ไม่ดีนะ

Angular ช่วยให้บริษัทระดับ Enterprise หลายๆ บริษัทสร้างหน้าเว็บออกมาได้สมบูรณ์มาก และมี feature ที่หลากหลายมาก เรียกได้ว่าแทบจะมีทุกอย่างที่ Frontend จะต้องการได้เลย

แต่ว่า ในบางกรณี แค่ HTML เปล่าๆ ก็มากพอแล้วสำหรับหน้าเว็ยหนึ่งหน้า

การที่เรา over-engineer มันซะทุกอย่างไม่ใช่เรื่องดีเลย เพราะเราทุกอย่างที่เราเลือกเพิ่มเข้ามาจะมี Opportunity Cost (ราคา) ของมันในการใช้อยู่

อย่างเช่นเว็บที่เขียนด้วย Angular จะต้องจ่ายค่า bundle size เริ่มต้นที่ 89.4KB อ้างอิงจาก bundlephobia | Angular 11.1

Cost of Angular

ซึ่งการที่จะต้องเพิ่มภาระ 89.4KB ก็ไม่ใช่เรื่องดีถ้าจะโหลดหน้าเว็ยซักหน้าที่มีแค่ material button และ text แน่ๆ เพราะแค่หน้า HTML เปล่าๆ ก็ทำได้เหมือนกัน

เริ่มจากแนวคิด

Code Department

ภาพประกอบของเกม Blue Archive

ก่อนสร้าง Salty Blog เป็น web blog ขึ้นมา สร้างขึ้นเพราะคนสร้างขี้เกียจที่จะสร้าง blog ใหม่ทุกครั้งที่ขี้เกียจ maintain และปัญหาจากการขี้เกียจที่จะ optimize blog ใหม่เรื่อยๆ จากปัญหาในการออกแบบเชิงโครงสร้าง และการลดขนาด ทุกครั้งที่เพิ่ม feature บางอย่างเข้าไป

ด้วยความขี้เกียจเลยจำเป็นที่จะต้องเลือก stack ที่คิดว่าใช้ได้ยาวๆ และเวลาแก้ต้องง่าย เลยตั้งใจว่าจะทำให้แทบทุกอย่างเป็น modular ไปซะหมดเลย เลยเลือกเอา atomic design มาใช้ในการออกแบบ

Atomic Design

โดยเริ่มจากสร้าง base component ที่คล้ายๆ กับ Design System เล็กๆ ของตัวเอง เพื่อเอาไว้ใช้ทำ abstraction ทุกๆ ครั้งที่มีการสร้าง component ใหม่ ก็ให้ abstract จาก molecule (โครงสร้างที่เล็กที่สุดของ atomic design) เช่น link, button, blog

แต่การทำ design system เล็กๆ ขึ้นมาก็เหนื่อยเหมือนกัน เลยเลือกใช้ Tailwind CSS เข้ามาช่วย ในการออกแบบ ซึ่งก็มี design abstraction มากจาก Tailwind อีกทีนึง

โชคดีที่ในการสร้าง blog ด้วย mdx จะต้องสร้าง component ขึ้นมาอยู่แล้ว เลยได้โอกาศสร้าง atomic component ทั้งหมดที่ต้องใช้ในทีเดียวเลย แล้วค่อย abstract ขึ้นไประดับ molecule และ organisms อีกทีนึง

Virtual DOM?

สั้นๆ คือ Virtual DOM เป็นหลักการที่เอา DOM Node มาหาจุดที่แตกต่างกันแล้วค่อยแก้ไขเฉพาะส่วนที่ต้องแก้อีกที ทำให้ได้ performance ที่ดีมากๆ ถ้าอยากอ่านเพิ่มก็มีบทความที่เคยเขียนเรื่องนี้อยู่เหมือนกัน

React เป็น Library แรกที่ใช้ Virutal DOM เข้ามาช่วย แล้วก็ขยายความนิยมไปจนมี library เยอะมากที่ใช้ Virtual DOM เช่น Vue

โดยหลักการโครงสร้างของ blog จริงๆ แล้วถ้าสังเกต คือในหน้า content แต่ละหน้าเนี่ย มักจะใช้รูปแบบเดิมแทบตลอด อย่างมากก็แค่เปลี่ยนตำแหน่งรูปและตัวอักษร แต่ถ้าลองสังเกตดีๆ คือ มักจะเป็น pattern เดิมเสมอ

เลยคิดว่าการเอา Virtual DOM เข้ามาใช้ในการสร้าง web blog ค่อยข้างที่จะเป็นความคิดที่ดีเลย ทำให้เลือกใช้ Virtual DOM ในการสร้าง

แต่ด้วยความที่เราไม่ได้อยากให้มันมีขนาดเล็กที่สุดเท่าที่จะทำได้ เลยเลือกใช้ Preact ที่เป็น alternative ที่มีขนาดแค่ 9kb แทน React

Next.js

Next.js เป็น Framework ที่ช่วยทำเรื่อง Server Side Rendering ให้ React อีกทีนึง

แต่นอกจากเรื่อง SSR แล้ว Next ยังช่วยหลายๆ เรื่อง อย่างเช่น optimize รูปภาพให้เอง, การทำ routing เอง, จัดการเรื่อง webpack หรือ TypeScript ให้เองด้วย ด้วยความสะดวก, ความขี้เกียจ และความที่มี community ที่ใหญ่มากๆ ถึงขนาดที่ทำงานกับทีม react ทำให้มี ecosystem ที่แทบจะมีทุกอย่างเลย แค่เลือกเอามาใส่ก็จบงานได้สบายๆ แล้ว

หลักๆ ที่เลือกใช้คือ

  • mdx ช่วยให้เขียน markdown แล้วแปลงเป็น react component
  • sass ที่ support โดย default

ด้วยความที่ไม่อยากเพิ่ม feature ที่ไม่ขำเป็นเยอะ เลยเพิ่มมาแค่นี้พอละ

คิดว่า blog ซัก blog ต้องมีอะไรมากหรอ? แค่เข้ามาอ่านได้ก็มากพอแล้ว

จากนั้นก็ alias react ให้เป็น preact แทน ทำให้ขนาดเรื่มต้นของ hello world โล่งๆ อยู่ที่ 28kb แต่ด้วยความที่เรารู้ว่ามันจะมามากกว่าหน้า landing แน่ๆ เลยเป็นเรื่องที่รับได้ เพราะยังไงก็ต้องเพิ่มแน่ๆ

mdx

หลังจากที่เลือก tech stack ได้คร่าวๆ แล้ว ก็ต้องคิดต่อว่าจะเขียน content ยังไง

ใจจริงแล้วอยากสร้าง drag-and-drop UI ไปเลย เพราะไม่อยากมานั่งจินตนาการตอนเขียนว่าจะออกมาเป็นยังไง แต่ตอนนี้ขอแค่ได้ฐานที่ดีก่อนแล้ว ค่อยไปทำ feature เพิ่มต่อก็ไม่สาย

เลยเลือกวิธีที่เป็นมิตรกับ dev มากๆ คือ ใช้ markdown ในการเขียน blog ไปเลย

ทีนี้ปัญหาคือทำยังไงให้มันเร็วและใช้ทรัพยาการน้อยที่สุด เพราะถ้าใช้ mdx ตรงๆ ตอนการทำ hydration จะต้อง hydrate data ของ component ที่เป็น base ด้วย ซึ่งถ้าเราใช้ Next Image ตรงๆ ก็พื่้นที่และ performance มากแน่ๆ

แต่โชคดีที่ไปเจอ next-mdx-remote ของ hashicorp พอดี ซึ่งหลักการง่ายๆ คือแทนที่จะไปทำทุกอย่างที่ client ก็ทำตอน build แทน ที่ getStaticProps ไปเลยดีกว่า แล้วให้ client hydrate เอา

ทำให้ตัว bundle size ของ next remote มีขนาดเล็กเอาซะมากๆ เพราะ compile ทุกอย่างเป็น json แทน ไม่ต้อง load component ในแต่ละหน้าทั้งหมดเป็น component

ซึ่งขนาดก็เพิ่มมาแค่นิดหน่อยคือ 4-5KB ได้ ซึ่งขึ้นอยู่กับขนาดของ component ที่เราใช้ด้วย แต่ยนาดเล็กกว่าตอนใช้ mdx เปล่าๆ แน่นอน

Tech stack

หลักๆ ก็ใช้เท่าที่จำเป็นจริงๆ ซึ่งขนาด state manager library ยังไม่มีเลย เพราะขอแค่คนเข้ามาอ่าน blog ได้ก็มากพอแล้ว

feature ที่ใช้ขนาด JavaScript ที่ใหญ่ที่สุดถ้าไม่นับ React กับ Next ก็คงเป็น Google Analytic ที่มีขนาดอยู่ที่ประมาณ 17KB ได้ ส่วนที่เหลือก็ไม่ได้ใช้อะไรแล้ว เพราะไม่รู้จะเพิ่มมาทำไม

ซึ่ง Tech stack ใหญ่ๆ ก็

  • Next.js + Preact (29KB)
  • TypeScript (0b)
  • next-mdx-remote (4-5KB โดยประมาณ)
  • prism.js (6.3KB)
  • jest (0kb)

และ layout และ component ที่ abstract ต่อกันมากเรื่อยๆ แทนการเขียนใหม่ ก็ช่วยลดขนาดไปได้อีกเยอะ ซึ่งสรุปได้ที่ประมาณเริ่มต้นที่ 39KB สำหรับหน้า landing และ 45KB สำหรับหน้า content

สรุป

ที่อยากจะบอกก็คือ ในการสร้างเว็บซักเว็บนึง พยายามอย่าทำให้มัน over engineer เกินไป เพราะนึกถึงจุดประสงค์ของเว็บที่เราจะทำเป็นหลัก เพราะว่ามันมี Opportunity Cost ในการเพิ่ม feature เสมอ

แล้วออกแบบโครงสร้างให้ดีก่อน ไม่งั้นจะมีปัญหาเรื่อง maintain ทีหลังแน่นอน บางทีการยอมเสียเวลาในการออกแบบฐานที่ดีจะช่วยให้เราไม่ต้องเสียเวลาแก้ปัญหาที่ปลายเหตุที่จะทำให้เราเสียเวลามากกว่าการออกแบบแน่ๆ

อย่างน้อยก็ทำให้เราขี้เกียจในภายหลักได้ เพราะไม่ต้องมานั่ง maintain หรือ optimize อะไรมากทีหลัง

สู้ทำฐานดีๆ ในตอนแรกให้มันดีๆ ไปเลย แทนที่จะต้องมาเสียเวลามากกว่าเดิมในภายหลังดีกว่า

Reading Book

ภาพประกอบของเกม Blue Archive