ทำไม Deploy จาก GitHub ไป Vercel สำเร็จ แต่เว็บที่เห็นจริงยังเป็นเวอร์ชันเก่า

สรุปสั้น ๆ
อาการ Deploy สำเร็จแต่เว็บยังเป็นเวอร์ชันเก่า ส่วนใหญ่เกิดจากสามสาเหตุหลัก คือดู URL ของ Preview Deployment แทน Production, ตั้ง Production Branch ผิด หรือ Browser/CDN แคชหน้าเดิมไว้ วิธีแก้คือตรวจ URL ที่ใช้ดู ตรวจ Branch Setting ใน Project และ Force Refresh ก่อนสรุปว่า Deploy มีปัญหา
อีเมลด่วนจากลูกค้าคนหนึ่งเขียนมาว่า 'ผม Push Code ไปแล้ว เห็น Vercel ขึ้นว่า Build สำเร็จ แต่เปิดเว็บจริงยังเห็นปุ่มเก่าอยู่เลย เกิดอะไรขึ้น' ผมถามกลับไปว่าเช็ค URL ไหนอยู่ เขาส่ง Link มาซึ่งพอดูดี ๆ กลับเป็น URL ของ Preview Deployment ที่มี Hash แปลก ๆ ต่อท้าย ไม่ใช่ Domain จริงของ Production เลย
เหตุการณ์แบบนี้เกิดขึ้นบ่อยมากกับทีมที่เพิ่งเริ่มใช้ Vercel เชื่อมกับ GitHub เพราะระบบ Preview Deployment ที่ทำให้ทุก Pull Request มี URL ทดสอบของตัวเองเป็นจุดแข็งอย่างหนึ่งของ Vercel แต่ก็เป็นจุดที่สร้างความสับสนได้ง่ายถ้าไม่เข้าใจว่า Deployment แต่ละแบบต่างกันตรงไหน
บทความนี้จะไล่ให้เห็นทีละสาเหตุที่ทำให้เกิดอาการ Deploy สำเร็จแต่เว็บไม่อัปเดตตามที่คาด พร้อมวิธีตั้งค่า Preview Environment ให้ทีมทำงานร่วมกันได้อย่างมั่นใจโดยไม่ต้องมานั่งเดาว่า URL ไหนคือของจริง
Vercel สร้าง Deployment กี่แบบเมื่อเชื่อมกับ GitHub
เมื่อเชื่อม Repository จาก GitHub เข้ากับ Vercel ระบบจะสร้าง Deployment อัตโนมัติตามเหตุการณ์ที่เกิดขึ้นใน Git หลัก ๆ มีสามแบบที่ต้องแยกให้ออก
- Production Deployment เกิดขึ้นเมื่อมีการ Push หรือ Merge เข้า Branch ที่ตั้งไว้เป็น Production Branch (ปกติคือ main หรือ master) ผูกกับ Domain จริงที่ผู้ใช้เข้าถึง
- Preview Deployment เกิดขึ้นทุกครั้งที่เปิด Pull Request หรือ Push เข้า Branch อื่นที่ไม่ใช่ Production Branch แต่ละ Preview มี URL เฉพาะของตัวเองที่มี Hash หรือชื่อ Branch ต่อท้าย
- Development Deployment เกิดจากการรัน `vercel` บนเครื่อง Local โดยตรง ไม่ผ่าน Git แต่ใช้สำหรับทดสอบก่อน Push จริง
สาเหตุที่หนึ่ง: ดู URL ของ Preview แทน Production
นี่คือสาเหตุที่พบบ่อยที่สุดตามตัวอย่างที่เล่าไปตอนต้น เมื่อเปิด Pull Request แล้ว Vercel Bot จะคอมเมนต์ URL ของ Preview Deployment ไว้ใต้ PR นั้นโดยอัตโนมัติ ถ้าทีมกด Copy Link จากคอมเมนต์นี้มาแชร์กันโดยไม่สังเกตว่าเป็น URL ของ Preview จะทำให้เข้าใจผิดว่ากำลังดู Production อยู่
วิธีตรวจง่ายที่สุดคือดูที่ Address Bar ของ Browser ถ้า Domain มี Hash ยาว ๆ หรือชื่อ Project ตามด้วย `-git-` แล้วตามด้วยชื่อ Branch นั่นคือ Preview Deployment ไม่ใช่ Production ที่ควรมี Domain สั้นตรงกับที่ตั้งค่าไว้ในหน้า Settings ของ Project
สาเหตุที่สอง: ตั้ง Production Branch ผิด
อีกกรณีที่พบบ่อยคือทีมที่ย้าย Branch หลักจาก master เป็น main แล้วลืมอัปเดต Production Branch ใน Vercel Project Settings ทำให้ Push เข้า main ไปแล้วจริง แต่ Vercel ยังรอดู Branch master ที่ไม่มีใคร Push เข้าไปอีกต่อไป Build ที่เห็นว่าสำเร็จอาจเป็น Build เก่าจาก Branch เดิมที่ค้างอยู่
ทีมที่ทำงานแบบ Multi-environment เช่นมี Branch staging แยกจาก main ก็ต้องตรวจให้แน่ใจว่าตั้ง Production Branch ตรงกับ Branch ที่ต้องการจริง ๆ ไม่ใช่ปล่อยค่า Default ไว้โดยไม่ตรวจสอบ เพราะค่า Default อาจไม่ตรงกับ Workflow ที่ทีมใช้งานจริงตั้งแต่ต้น
สาเหตุที่สาม: Cache ทั้งฝั่ง CDN และ Browser
แม้ Deploy จะสำเร็จและ Domain ถูกต้องแล้ว บางครั้งผู้ใช้ยังเห็นเวอร์ชันเก่าเพราะ Cache ที่เก็บไว้ทั้งฝั่ง Browser ของผู้ใช้เองและฝั่ง CDN ของ Vercel ที่กระจายไปหลาย Edge Location ทั่วโลก
Vercel มีระบบ Invalidate Cache อัตโนมัติเมื่อ Deploy สำเร็จ แต่ในบางกรณีที่ตั้งค่า Cache-Control Header เองแบบ Aggressive มากเกินไปในโค้ด อาจทำให้ Browser ของผู้ใช้บางคนยังเก็บหน้าเวอร์ชันเก่าไว้นานกว่าที่ควร การ Force Refresh (Ctrl+Shift+R หรือ Cmd+Shift+R) หรือเปิดใน Incognito มักช่วยยืนยันได้เร็วว่าปัญหาจริง ๆ อยู่ที่ Cache หรือที่ Deployment
ตารางไล่สาเหตุแบบเร็ว
เมื่อเจออาการนี้ ลองไล่ตามตารางนี้ทีละแถวเพื่อหาสาเหตุที่แท้จริง:
| อาการที่สังเกตได้ | สาเหตุที่เป็นไปได้ | วิธีตรวจสอบ |
|---|---|---|
| URL มี Hash หรือ -git- ต่อท้าย | กำลังดู Preview ไม่ใช่ Production | เทียบกับ Domain ที่ตั้งไว้ใน Settings |
| Deployment History ไม่มี Build ใหม่ | Production Branch ตั้งผิด | ตรวจ Settings > Git > Production Branch |
| Deploy สำเร็จ แต่ Browser ยังเห็นของเก่า | Cache ฝั่ง Browser | Force Refresh หรือเปิด Incognito |
| Deploy Log มี Error แต่ขึ้นว่าสำเร็จ | Build ผ่านแต่ Runtime Error แยกต่างหาก | ดู Function Log แยกจาก Build Log |
ตั้ง Preview Environment ให้ทีมทำงานร่วมกันได้อย่างมั่นใจ
เพื่อลดความสับสนแบบนี้ในทีม ควรวางกฎที่ชัดเจนตั้งแต่ต้นว่าทุกคนดู Production ที่ Domain จริงเท่านั้นเวลาจะยืนยันว่า Feature ขึ้นจริงแล้ว ไม่ใช้ URL จาก Comment ของ PR มาใช้อ้างอิงแทน
- ตั้งชื่อ Production Domain ให้จำง่ายและแชร์ให้ทุกคนในทีมรู้ตรงกันว่านี่คือ URL เดียวที่ใช้ยืนยัน Production
- เปิด Vercel Bot Comment บน GitHub PR ไว้เพื่อสะดวกในการรีวิว แต่กำชับทีมว่า URL ในคอมเมนต์นั้นคือ Preview เท่านั้น
- ตั้งค่า Environment Variables ให้ Preview กับ Production ชี้ไปคนละชุด Database หรือ Service ภายนอก ป้องกันไม่ให้การทดสอบใน Preview กระทบข้อมูลจริง
- ตรวจ Production Branch ใน Settings ทุกครั้งหลังเปลี่ยนโครงสร้าง Branch หลักของ Repository เพื่อไม่ให้ Deploy ค้างอยู่ที่ Branch เก่า
วาง Workflow ทีมให้ Deploy ไม่สร้างความสับสนซ้ำอีก
ทีมที่เจอปัญหานี้ซ้ำ ๆ มักไม่ใช่เพราะเทคนิคผิด แต่เพราะไม่มี Convention ร่วมกันว่าใครมีหน้าที่ตรวจสอบอะไรก่อน Merge เข้า Production Branch การกำหนดขั้นตอนง่าย ๆ เช่น ให้คนที่ Merge PR เป็นคนสุดท้ายที่ต้องเปิด Production Domain จริงเพื่อยืนยันว่า Feature ขึ้นถูกต้อง ช่วยลดความผิดพลาดแบบนี้ได้มาก
อีกแนวทางที่หลายทีมใช้คือเชื่อมต่อ Vercel เข้ากับ Slack หรือ Discord เพื่อรับแจ้งเตือนทุกครั้งที่มี Production Deployment สำเร็จ พร้อมลิงก์ที่ระบุชัดว่าเป็น Production URL ไม่ใช่ Preview ทำให้ทั้งทีมเห็นสถานะตรงกันโดยไม่ต้องเปิด Dashboard เข้าไปเช็คเอง และลดโอกาสที่ใครสักคนจะหยิบ URL ผิดมาแชร์ต่อในช่องทีม
สำหรับทีมที่ใช้เครื่องมือสร้าง App ด้วย AI อย่าง v0 แล้ว Deploy ต่อผ่าน GitHub ควรระวังเป็นพิเศษ เพราะ Commit ที่เกิดจาก AI Agent อาจมาถี่กว่าปกติในช่วงที่กำลังทดลองปรับ UI ทำให้ Preview Deployment เกิดขึ้นบ่อยและอาจมี URL ทดสอบเก่าค้างอยู่หลายอันพร้อมกันถ้าไม่ได้ปิด Pull Request ที่ทดลองเสร็จแล้ว
ถ้า Deploy ผิดจนกระทบผู้ใช้ ควร Rollback ยังไงให้เร็วที่สุด
อีกสถานการณ์ที่ต่างจากอาการ 'เห็นเวอร์ชันเก่า' คือกรณีตรงข้าม คือ Deploy สำเร็จและอัปเดตจริง แต่เวอร์ชันใหม่กลับมีบั๊กที่กระทบผู้ใช้ทันที เช่นหน้า Checkout พังหรือ Login ไม่ได้ กรณีแบบนี้ต้องแก้เร็วที่สุดโดยไม่ต้องรอ Fix Code แล้ว Deploy รอบใหม่
Vercel เก็บประวัติทุก Production Deployment ไว้ ทำให้กด Promote to Production ย้อนกลับไปยัง Deployment ก่อนหน้าที่ยังทำงานปกติได้ภายในไม่กี่วินาที โดยไม่ต้องรอ Build ใหม่เลย เพราะ Deployment เก่ายังถูกเก็บไว้พร้อมใช้งานอยู่แล้วในระบบ
ทีมควรซ้อมขั้นตอนนี้ไว้ล่วงหน้าก่อนเกิดเหตุจริง เพราะตอนเกิดปัญหาจริงมักมีความกดดันสูง การรู้ล่วงหน้าว่าต้องกดตรงไหนใน Dashboard ช่วยลดเวลาที่ผู้ใช้เจอปัญหาลงได้มาก ควรกำหนดด้วยว่าใครในทีมมีสิทธิ์กด Rollback ได้โดยไม่ต้องรอขออนุมัติก่อน เพราะทุกนาทีที่ผู้ใช้เจอ Error มีค่าเสียโอกาสจริง
หลัง Rollback สำเร็จแล้ว ควรแยก Branch สำหรับแก้บั๊กออกมาต่างหากและทดสอบใน Preview Deployment ให้แน่ใจก่อนจะ Merge กลับเข้า Production Branch อีกครั้ง ไม่ควรรีบ Push Fix แบบเร่งรีบกลับเข้า Production ทันทีโดยไม่ผ่าน Preview เพราะอาจสร้างปัญหาใหม่ซ้อนปัญหาเดิม
Deploy จาก Monorepo ที่มีหลาย Project ใน Repository เดียว
ทีมที่ใช้ Monorepo เก็บทั้ง Frontend, Backend และ Package ที่ใช้ร่วมกันไว้ใน Repository เดียว มักเจอคำถามเพิ่มว่าจะทำให้ Vercel Deploy เฉพาะ Project ที่เกี่ยวข้องเมื่อมีการแก้ไฟล์ ไม่ใช่ Build ทุก Project ทุกครั้งที่มี Commit ใหม่
Vercel รองรับการตั้งค่า Root Directory และ Ignored Build Step ที่ให้ตรวจว่า Commit นั้นแก้ไฟล์ในโฟลเดอร์ที่เกี่ยวข้องกับ Project นี้จริงหรือไม่ ถ้าไม่เกี่ยวก็ข้าม Build รอบนั้นไปเลย ช่วยประหยัดทั้งเวลาและ Build Minutes ที่ต้องจ่าย
จุดที่ทีม Monorepo มักพลาดคือลืมตั้ง Ignored Build Step ให้ครบทุก Project ทำให้ทุกครั้งที่มีคน Commit แก้ไฟล์เล็ก ๆ ใน Project หนึ่ง กลับไป Trigger Build ของทุก Project พร้อมกัน สิ้นเปลืองทั้งเวลาที่ทีมต้องรอและโควตา Build ที่ใช้ร่วมกันในองค์กรเดียวกัน ควรตรวจการตั้งค่านี้ให้ครบทุก Project ตั้งแต่วันแรกที่เชื่อม Monorepo เข้ากับ Vercel
ตัวอย่างสมมติ: ทีมแก้ปัญหานี้ได้ถาวรยังไง
ลองสมมติทีมหนึ่งเจออาการนี้ซ้ำเกือบทุกสัปดาห์ เพราะสมาชิกใหม่ในทีมมักหยิบ URL จาก Comment ของ PR มาส่งให้ฝ่ายขายดูตอนสาธิต Feature ทำให้เกิดความเข้าใจผิดหลายครั้งว่า Production ยังไม่อัปเดต ทั้งที่จริง ๆ อัปเดตไปแล้วตั้งแต่เมื่อวาน
หลังจากตั้งกฎง่าย ๆ ว่า URL ที่ใช้สาธิตลูกค้าต้องเป็น Production Domain เท่านั้น พร้อมเพิ่มขั้นตอนให้คนที่ Merge PR โพสต์ยืนยันใน Slack ว่า 'Production Deployed แล้ว เช็คที่ [Domain จริง]' ทุกครั้งหลัง Merge ปัญหาความสับสนแบบนี้ก็หายไปเกือบหมดภายในสองสัปดาห์ (สถานการณ์นี้เป็นตัวอย่างสมมติเพื่อประกอบการอธิบาย)
ทำแบบนี้แล้วพัง เพราะอะไร
- แชร์ URL จาก Comment ของ Pull Request ให้ลูกค้าหรือทีมอื่นดูโดยไม่บอกว่าเป็น Preview ทำให้เกิดความเข้าใจผิดว่า Production อัปเดตหรือยังไม่อัปเดตผิดจากความจริง
- เปลี่ยนชื่อ Branch หลักแล้วลืมอัปเดต Production Branch ใน Settings ทำให้ Push เข้า Branch ใหม่ไม่มีผลกับ Production เลย
- ตั้ง Cache-Control Header แบบ Aggressive มากเกินไปโดยไม่เผื่อกรณีต้อง Deploy ด่วน ทำให้ผู้ใช้บางคนเห็นเวอร์ชันเก่าค้างนานผิดปกติ
- ไม่ปิด Preview Deployment ที่ทดลองเสร็จแล้ว ปล่อยให้ URL เก่าเปิดใช้งานได้เรื่อย ๆ จนมีคนหยิบผิดมาใช้อ้างอิงภายหลัง
- เข้าใจว่า Build สำเร็จแปลว่าไม่มีปัญหาอะไรเลย ทั้งที่ Build Log กับ Runtime Log เป็นคนละส่วนกัน บาง Error เกิดขึ้นตอนมีคนเข้าใช้งานจริงเท่านั้น ไม่ใช่ตอน Build
สรุป
อาการ Deploy สำเร็จแต่เว็บยังเป็นเวอร์ชันเก่าแทบทุกครั้งไม่ได้มาจากปัญหาทางเทคนิคที่ซับซ้อน แต่มาจากการเข้าใจผิดเรื่อง Preview กับ Production Environment ที่ Vercel ออกแบบมาให้ทำงานคู่กันตั้งแต่ต้น
วิธีป้องกันที่ได้ผลที่สุดคือวาง Convention ให้ทีมชัดเจนว่า Production Domain คืออะไร ใครมีหน้าที่ยืนยันหลัง Merge และตั้งค่า Production Branch ให้ตรงกับ Workflow จริงเสมอ ไม่ใช่ปล่อยตามค่า Default
- ตรวจ URL ก่อนเสมอ ว่ากำลังดู Preview หรือ Production Domain จริง
- ตรวจ Production Branch ใน Settings ให้ตรงกับ Branch หลักที่ใช้งานจริง
- Force Refresh หรือเปิด Incognito เพื่อตัดปัญหา Cache ฝั่ง Browser ก่อนสรุปว่า Deploy มีปัญหา
- วาง Convention ให้ทีมยืนยัน Production URL หลัง Merge ทุกครั้งเพื่อลดความสับสน
คำถามที่พบบ่อย
ทำไม Vercel Bot คอมเมนต์ URL ที่ไม่ใช่ Production ใต้ PR
เพราะ URL นั้นคือ Preview Deployment ที่สร้างขึ้นเพื่อให้รีวิว Feature ก่อน Merge ไม่ใช่ URL ของ Production ควรใช้ยืนยันความถูกต้องของ Feature ก่อน Merge เท่านั้น ไม่ใช้แชร์แทน Production
แก้ Production Branch ผิดแล้วจะกระทบ Deployment เก่าที่มีอยู่ไหม
ไม่กระทบ Deployment ที่เกิดไปแล้วจะยังอยู่ในประวัติ แต่ Production Domain จะไม่อัปเดตตาม Push ใหม่จนกว่าจะแก้ Production Branch ให้ตรงกับ Branch ที่ใช้งานจริง
ทำ Force Refresh แล้วยังเห็นของเก่าอยู่ควรทำยังไงต่อ
ลองเปิดใน Incognito หรืออุปกรณ์อื่นเพื่อตัดปัญหา Cache ฝั่ง Browser ถ้ายังเห็นของเก่าให้ตรวจ Deployment History ใน Vercel Dashboard ว่า Production Deployment ล่าสุดตรงกับ Commit ที่คาดไว้จริงหรือไม่
Preview Deployment ใช้ Database เดียวกับ Production ได้ไหม
ทำได้ทางเทคนิคแต่ไม่แนะนำ เพราะการทดสอบใน Preview อาจไปแก้ข้อมูลจริงโดยไม่ตั้งใจ ควรแยก Environment Variables ให้ Preview ชี้ไปที่ Database สำหรับทดสอบแยกต่างหาก
Build Log ขึ้นว่าสำเร็จ แต่ผู้ใช้เจอ Error ตอนใช้งานจริง เป็นไปได้ไหม
เป็นไปได้ เพราะ Build Log ตรวจแค่ว่า Code Compile ผ่าน ไม่ได้ตรวจ Runtime Error ที่เกิดเฉพาะตอนมีคนเข้าใช้งานจริง ควรดู Function Log แยกต่างหากเพื่อหาสาเหตุ
ควรลบ Preview Deployment เก่าทิ้งไหม
ควรปิด Pull Request ที่ทดลองเสร็จแล้วเพื่อไม่ให้ Preview URL เก่าเปิดใช้งานค้างอยู่ ลดโอกาสที่ใครหยิบ URL เก่าไปใช้อ้างอิงผิดในภายหลัง
อ่านต่อแบบเจาะลึก
ทดลองวัดผลโฆษณาเข้า LINE ฟรี 14 วัน
สมัครแล้วสร้างโปรเจกต์ เชื่อม LINE ติดตั้ง Tracking แล้วเริ่มเห็น Funnel จาก Click ถึง Purchase ได้ทันที ไม่ต้องใช้บัตรเครดิต
เริ่มทดลองใช้ฟรี 14 วันบทความที่เกี่ยวข้อง

เขียนแอปเสร็จแต่ยังไม่มีฐานข้อมูล ทีมเล็กควรเริ่มจาก Supabase ยังไง

ทำไมทีมสร้าง AI Application ยุคนี้ถึงเลือก Supabase แทนการต่อฐานข้อมูลเวกเตอร์แยก
