รองรับคนเป็นล้าน จ่าย 0 บาทด้วย WordPress+Next.js


SSG vs Static generation

Updated On November 14, 2023 by Adisak Chaiyakul

cover

วันนี้ผมจะมาเล่าถึงเบื้อหลังเว็บไซด์ klabban.com ว่าผมทำมันยังไงโดยที่ไม่ต้องจ่ายค่า host เลยทั้งที่ยังใช้ข้อมูลมาจาก wordpress cms อยู่

Static generation?

ข้อดี หลายๆคนอาจจะรู้ว่า Next.js เองสามารถทำ static generation website ได้ทำให้เราได้ไฟด์ export มาในรูปแบบ HTML และเอาไปโยนใน static host ธรรมดาๆได้เลย เช่นพวก S3. ทำให้เว็บไซด์โหลดได้อย่างรวดเร็วและโหลด resource เท่าที่จำเป็นเท่านั้น และอีกอย่างคือทำให้เราไม่ต้องจ่ายค่า server ของ WordPress หรือ backend อะไรก็ตามที่เราใช้ในการดึงข้อมูลมา เราสามารถลง wordpress ในเครื่องแล้วเขียนบทความในเครื่อง build และ deploy ได้เลยโดยไม่จำเป็นต้องมี server WordPress จริงๆ

ข้อเอ๊ะๆๆๆๆ Static Generation เหมาะสำหรับเว็บไซด์ที่ไม่จำเป็นต้องอัพเดตข้อมูลแบบ Real time เพราะหากต้องการเปลี่ยนแปลงข้อมูลของเว็บไซด์ก็จะต้อง build และ deploy ใหม่ การเขียนและ config ก็จะต้องเขียนมาเพื่อที่จะทำ Static Generation โดยเฉพาะ เช่นการอ้างอิงรูปภาพหรือ feature บางอย่างก็จะใช้ไม่ได้ ทำให้หากวันหนึ่งเราต้องการที่จะ scale ให้เว็บมีความสามารถอื่นๆเพิ่มเติมที่ต้องใช้ความสามารถของ server ก็อาจจะต้องแก้เยอะหน่อย

เพราะฉะนั้นมันก็ต้องเลือกหลักๆว่าอยากได้ Sped, cost หรือ real time, more feature

I want best of both world but how?

  1. ผมต้องการที่จะใช้ WordPress เป็นที่เก็บข้อมูลโดยที่ไม่ต้องการจ่ายค่า server
  2. ผมต้องการให้เว็บไซด์เขียนด้วยวิธีปกติพร้อมที่จะ scale ไม่ต้องการเขียนด้วยการคิดแบบ static generation แล้วอนาคตต้องมาเปลี่ยนทีหลัง

วิธีก็คือ SSG และ force-static option

SSG

SSG มันคือการ render HTML เตรียมไว้ตั้งแต่ตอน build โดยเราเป็นคนกำหนดว่าจะให้ render หน้าไหนบ้าง ซึ่ง SSG กับ static generation มันต่างกันตรงที่ static มันจะได้ html CSS file ออกมาเลยแต่ การใช้ SSG จะเป็นการ build แบบปกติและใช้ feature ของ Next.js ได้ครบทุกอย่าง

เราสามารถทำ SSG ได้โดยการใช้ generateStaticParams

export async function generateStaticParams() {
  
 
  const blogsData = await fetchBlogData({
    limit: 1000
  })

  return (
    blogsData.map((blog) => ({
      blogSlug: blog.slug,
    }))
  );
}

ซึ่งใน function นี้เราได้ระบุว่าเราจะให้ Next.js render หน้าไหนเตรียมไว้ตอน build time บ้างโดยการดึงข้อมูลจาก wordpress ว่ามี blog เท่าไหร่มี slug เป็นอะไรบ้างแล้วส่งให้ Next.js

แต่นี่ยังไม่เพียงพอเพราะหากเรา build และลอง start server “pnpm build” และ “pnpm start” เว็บไซด์เราจะเร็วมากเหมือนไม่ต้องดึงข้อมูลจาก wordpress เลยก็เพราะเราสั่งให้มันดึงไว้ตั้งแต่ build time แล้ว

แต่หากเราปิด server WordPress ใน local เมื่อไหร่เว็บก็จะแสดง 404 หรือ 500 Error ทันที อันนี้ผมก็ไม่ชัว 100% ว่าทำไมเดียวต้องไปเปิดห้องทดลองอีกทีแต่สมมุติฐานก็คือ จริงๆแล้วหน้านี้เป็น Server Component ซะส่วนมากและใน Main Navigation มีการ ดึงข้อมูลจาก WordPress เช่นเดียวกันเมื่อเราปิด Server ทำให้เกิด 500 Error ได้

Force Static

วิธีแก้ก็คือเราสามารถ ตั้งค่า Dynamic route config ของหน้านั้นๆใหม่โดยการใช่ config นี้เข้าไป

export const dynamic = "force-static";

ก็จะทำให้ dynamic route นั้นเป็น static โดยสมบูรณ์

Deploy ยังไง?

ถ้าเป็น Static export เราสามรถ build แล้วได้ไฟด์ html css แล้วเอาไปโยน ใน S3 ได้เลยใช่มั๊ย แต่แบบของเราจะทำแบบนั้นไม่ได้

Vercel CLI

แบบที่หลายๆคนรู้ vercel เป็น hosting ที่เป็นผู้สนับสนุนหลักของ Next.js เพราะฉะนั้นมัน friendly กับ Next.js มากๆอยู่แล้ว โดยปกติทั่วไปเวลาเราจะ deploy Next.js เราก็จะต่อ Vercel account กับ git repo ที่เราต้องการจะ deploy ใช่มั๊ยและเมื่อมีการ push code ขึ้นไปเมื่อไหร่ Vercel ก็จะทำการ build และ deploy โปรเจคของเราให้อัตโนมัติ

แต่เราจะทำแบบนั้นไม่ได้ในกรณีนี้เพราะ Server WordPress ของเราอยู่บนเครื่อง (Local) ทำให้เมื่อ Vervcel build จะหา Server ไม่เจอแล้วก็จะ Error

วิธีแก้ก็คือการต้อง build ที่ Local แล้วเอาไฟด์ที่ build ไป deploy

ก่อนอื่นคุณก็ต้องไป install vercel cli ก่อนนะ

ืnpm install -g vercel-cli 

จากนั้นก็ login ด้วยคำสั่ง

vercel login

แล้วก็ใช้สองคำสั่งนี้

vercel build --prod

แล้ว vercel ก็จะถามให้ set up อะไรต่างๆอันนี้ก็ลองไปอ่านๆดูกันเอาละกัน

สุดท้ายก็ deploy ด้วยคำสั่ง

vercel deploy --prebuilt --pro

เพียงเท่านี้เว็บเราก็จะพร้อมใช้งานโดยที่ไม่ต้องมี WordPress Server แล้ว

รูปหาย

อีกหนึ่งปัญหาสุดท้ายก็คือเวลาคุณ deploy ไปแล้วรูปคุณจะหาย เป็นเพราะว่าเว็บไซด์ยังอ้างอิงรูปไปยัง localhost เพราะ Server WordPress ของคุณมันอยู่ที่ localhost วิธีแก้ก็ง่ายๆด้วยการใช้

Cloundinary

เราก็ใช้ CND ในการเก็บรูปด้วย cloundinary wordpress plugin ไปเลยง่ายๆ คุณก็ไปลง plugin ตัวนี้แล้วก็ทำตาม step ที่ plugin แนะนำ. หลังจากรอซักพักเมื่อ cloundinary ทำงานเสร็จ url เว็บไซด์ทั้งเว็บของคุณตอนนี้ก็จะเปลี่ยนเป็น link ของ CND เช่น https://res.cloudinary.com/xxxxx/xxxx แล้วทำให้รูปสามารถเข้าถึงได้จาก internet เพียงเท่านี้เว็บเราก็จะมีรูปแล้ว

สรุป

สรุปแล้วมันต่างจาก static generation ยังไงวะสุดท้ายก็ทำ static ยุดีป่ะ?

มันต่างกันอยู่เพราะหากวันไหนคุณเปลี่ยนใจคุณสามารถ สร้าง WordPress Server แล้วต่อเข้ากับ front-end ตัวนี้แล้วเว็บคุณก็จะเป็นเว็บที่ สามารถอัพเดต real time ได้ปกติเลย (แต่ต้องทำ webhook สำหรับ revalidate หน่อยนะ)

สรุปจบในบรรทัดเดียว

next.js SSG with dynamic config = force static + vercel cli deploy + cloundinary

ถ้าอ่านแล้วงง (งงแน่นอน) ผมต้องขออภัยด้วยแล้วผมจะปรับปรุงวิธีการเล่าเรื่องให้ดีขึ้นเรื่อยๆ มีอะไรก็สอบถามผมเข้ามาได้ในช่องทาง Social Media ได้เลย

cover

Craft by

Adisak Chaiyakul

Developer ที่ชอบปั่นจักรยาน รักในเสียงดนตรี และการท่องเที่ยวธรรมชาติ มีความพยายามที่จะหา solution สำหรับ SME และคนตัวเล็กที่จะเอาชนะความเหลื่อมล้ำทางโอกาศด้วยเทคโนโลยี สนใจและเสพเนื้อหาแทบทุกเรื่องแต่สื่อสารไม่ได้เก่ง แต่กำลังพัฒนาตัวเองอยู่นะ

เนื้อหาที่เกี่ยวข้อง

Klabban.com