เมื่อความเรียบง่ายคือคำตอบ
ช่วงแรกที่เริ่มเขียนบล็อก เราเลือกใช้ Ghost แบบ self-host เพราะมันดู modern, editor ใช้งานดี
Ghost รันผ่าน Docker ใน homelab ที่บ้าน แล้วเชื่อมต่อออกไปข้างนอกด้วย Cloudflare Tunnel + โดเมนของเราเอง ทุกอย่างทำงานได้ดี
…จนเวลาผ่านไป เราเริ่มรู้สึกว่าเวลาเปิดหน้าเว็บ มันหน่วงขึ้นนิดหน่อย ไม่มากก็จริง แต่ก็พอจะรู้สึกได้ และเริ่มน่ารำคาญขึ้นเรื่อย ๆ
ที่แย่กว่านั้นคือ มีอยู่วันหนึ่งไฟที่บ้านดับยาวทั้งวัน UPS ที่ต่อกับ homelab เอาไม่อยู่ เว็บเลยดับหายไปทั้งวันแบบดื้อ ๆ 😅
ตอนนั้นแอบคิดในใจว่า “นี่เรากำลังโฮสต์บล็อกตัวเอง หรือกำลังดูแล data center กันแน่นะ”
ถึงเวลาหาอะไรใหม่ที่เบากว่า
จริง ๆ แล้วเราก็ไม่ได้ต้องการระบบ CMS อะไรใหญ่โตเลย
- เขียนโพสต์ง่าย ๆ ด้วย Markdown
- Publish ได้ไว ไม่ต้องรอระบบอะไรทั้งนั้น
- ใช้ Git จัดการเวอร์ชันได้สะดวก
- ไม่ต้องรัน server หรือ database ให้ปวดหัว
พอลองหาดู static site generator ที่ตอบโจทย์พวกนี้ เราก็มาเจอกับ Hugo ตัวเล็ก เร็ว และเรียบง่าย
Compile แต่ละรอบแค่เสี้ยววินาที
ใช้งานไม่ยาก และ deploy ขึ้น GitHub Pages หรือ Cloudflare Pages ได้ทันทีแบบไร้ server
จากนั้นก็เริ่มย้ายบล็อกทันที…
เราต้องหาเครื่องมือสำหรับช่วยแปลงข้อมูลจากไฟล์ JSON ที่ export มาจาก Ghost
ให้กลายเป็นไฟล์ Markdown ที่พร้อมใช้งานกับ Hugo ได้เลย
จนไปเจอ ghostToHugo เครื่องมือที่ช่วยแปลงโพสต์จาก Ghost ให้อยู่ในโครงสร้างของ Hugo
แต่ปัญหาก็คือ… ข้อมูล HTML บางส่วน โดยเฉพาะรูปภาพ ดันหายไป! จะให้แก้ทีละโพสต์ก็ไม่ไหวแน่ เลยตัดสินใจเขียนสคริปต์ขึ้นมาเองดีกว่า
ไหน ๆ ก็ทำแล้ว ก็เลยเอาขึ้น GitHub เผื่อใครเจอปัญหาเดียวกันจะได้ใช้งานต่อได้เลย
พอข้อมูลพร้อมแล้ว ก็ถึงเวลาจัดหน้าตาเว็บใหม่
เราเลือกใช้ theme PaperMod เพราะมันดูเรียบง่าย โหลดเร็ว และมีฟีเจอร์ที่ครบพอสมควร โดยเฉพาะเรื่อง SEO ที่จัดการทั้ง metadata, structured data และ share preview ได้ดี
ส่วนการ deploy เราใช้ Cloudflare Pages เพราะเชื่อมกับ Git ได้สะดวก แก้ไฟล์ใน repo แล้วมัน build ให้อัตโนมัติ แถมเร็วด้วย (และฟรี!)
แต่พอ deploy เสร็จ เราก็เจอปัญหาใหม่จนได้… โครงสร้าง URL มันเปลี่ยนไป!
จากเดิมที่ Ghost ใช้ /slug/
พอย้ายมา Hugo แล้วกลายเป็น /posts/slug/
แทน 😅
โอ้ยยย เสียดาย index เก่าใน Google
สุดท้ายเราแก้ด้วยการใช้ Cloudflare Redirects ให้ช่วย map ใหม่แบบ permanent redirect (301)
ใน repo ghost-to-hugo เราก็เลยเขียนสคริปต์ไว้สำหรับ generate redirect ของแต่ละ slug ให้เรียบร้อยแล้ว แค่เอาไฟล์ที่ได้ไปวางใน project ก็พร้อมใช้งาน ไม่ต้องไล่เขียนเองทีละบรรทัดให้เหนื่อย
แต่ก็ยังมีบางส่วนที่ต้องเติมเองเล็กน้อย เช่น redirect ของหน้า tag เพราะ Ghost ใช้ /tag/:slug/
แต่ Hugo เปลี่ยนเป็น /tags/:slug/
แบบนี้ต้องเขียนเพิ่มเองในไฟล์ _redirects
ประมาณนี้
/tag/:slug/ /tags/:slug/ 301
แล้วเร็วขึ้นจริงไหม?
เราทดสอบความเร็วเว็บไซต์หลังจากย้ายมา Hugo โดยใช้
PageSpeed Insights
ของ Google
ผลออกมาคือ…
- 🚀 Mobile: 100/100
- ⚡ Desktop: 100/100
- ⏱️ First Contentful Paint (FCP): ประมาณ 0.9s
- 🧼 Total Size: ~50KB (ไม่มี JS framework, ไม่มี database, ไม่มี backend)
จากเดิมที่เคยรอ Ghost โหลด admin, load database, load theme ตอนนี้เปิดเว็บแล้วมันมาเลย ไม่มีอะไรต้องรอ
พูดง่าย ๆ คือ “คลิกแล้วมา” แบบ static site ของจริง