Understand the shape
รู้จักโครงสร้างก่อนลงมือ
โครงการนี้เป็นเว็บแบบ full-stack ที่แบ่งหน้าที่ระหว่าง static assets กับ edge API อย่างชัดเจน หน้าเว็บที่ผู้ใช้เปิดอยู่ในโฟลเดอร์ public/ ส่วน API ที่เข้าถึง D1 อยู่ใน Pages Function แบบ catch-all ที่ functions/api/[[route]].js เมื่อรัน Local Dev, Wrangler จะประกอบสองส่วนนี้ให้ทำงานผ่าน origin เดียวกัน
public/js/*
Pages Functions
schema.sql
ระหว่าง local development เราใช้ D1 local ที่แยกจาก production ส่วนคำสั่งที่มี --remote จะเปลี่ยนข้อมูลบน Cloudflare จริง จึงไม่ควรทดลองด้วย flag นี้จนกว่าจะตรวจสอบ SQL เรียบร้อย
Before you start
เตรียมเครื่องมือและตรวจไฟล์
ใช้ Terminal เปิดจากโฟลเดอร์ที่มีไฟล์ wrangler.toml และ package.json ของโครงการนี้ หากยังไม่ได้แตกไฟล์ ให้แตก ZIP ก่อนแล้วเข้าไดเรกทอรี hotel-repair-db
node --versionโครงการใช้ Node สำหรับ npm และ Wrangler เท่านั้นnpx wrangler loginจำเป็นเมื่อสร้าง D1 หรือ deploy remotenpm installติดตั้ง Wrangler ตาม package-lock.jsonnode --version
npx wrangler --version
npm install
npm run check
ค่า name = "hotel-repair-pages" ใน wrangler.toml ต้องตรงกับชื่อ Pages project ใน Dashboard เพื่อ deploy กลับ URL เดิมและไม่สร้าง project ใหม่โดยไม่ตั้งใจ
Database foundation
สร้างและผูก Cloudflare D1
D1 คือฐานข้อมูล SQL ที่ Pages Function เข้าถึงผ่าน binding ใน Wrangler configuration สำหรับโครงการนี้ binding ต้องใช้ชื่อ DB เพราะ backend เรียกผ่าน env.DB โดยตรง
ตรวจว่ามี database อยู่แล้วหรือยัง
เริ่มจากดูรายการ D1 ในบัญชีที่ login อยู่ หากเห็น hotel-repair-db ให้ใช้ database เดิมและไม่ต้องสร้างซ้ำ
npx wrangler d1 listสร้าง D1 ใหม่ กรณียังไม่มี
รันคำสั่งนี้เพียงครั้งเดียว เมื่อสร้างสำเร็จ Wrangler จะแสดง database_id ให้นำไปใส่ใน wrangler.toml
npx wrangler d1 create hotel-repair-dbdatabase_name และ database_id ใน wrangler.toml เป็นของ database เดียวกันตรวจ binding ใน wrangler.toml
ไฟล์ของโครงการนี้ต้องมีส่วนสำคัญใกล้เคียงกับตัวอย่างด้านล่าง ค่า ID ใช้ของจริงจากบัญชีคุณ ไม่ควรคัดลอก ID ของคนอื่น
name = "hotel-repair-pages"
pages_build_output_dir = "./public"
compatibility_date = "2026-08-25"
[[d1_databases]]
binding = "DB"
database_name = "hotel-repair-db"
database_id = "ใส่-database-id-ของคุณที่นี่"| คีย์ | ความหมาย | ค่าที่ต้องระวัง |
|---|---|---|
name | ชื่อ Pages project | ต้องตรงกับ Dashboard |
pages_build_output_dir | โฟลเดอร์ไฟล์เว็บ | โครงการนี้คือ ./public |
binding | ชื่อตัวแปรใน Function | ต้องเป็น DB |
database_id | ID ฐานข้อมูล D1 | ไม่ใช่ database name |
ผูก D1 ผ่าน Dashboard กรณีใช้ Git integration
- เปิด Workers & Pages แล้วเลือก Pages project ของระบบ
- ไปที่ Settings → Bindings แล้วกด Add → D1 database bindings
- กำหนด Variable name เป็น
DB - เลือก database
hotel-repair-dbแล้วกด Save - สร้าง deployment ใหม่ เพราะ binding จะมีผลหลัง redeploy
Local feedback loop
รัน Cloudflare Pages Local Dev
Local Dev จะจำลองทั้ง static frontend และ Pages Functions บนเครื่องเดียวกัน ทำให้ทดสอบ API, D1 query และหน้าเว็บด้วย origin เดียวกันได้โดยไม่ต้อง deploy ทุกครั้ง ข้อมูลที่ migrate ด้วย --local จะอยู่ใน state ของ Wrangler และไม่แก้ D1 production
npm run d1:migrate:localนำ schema.sql และ seed data เข้า D1 localnpm run devเสิร์ฟที่ localhost:8788curl /api/configทดสอบก่อน deploy จริงnpm run d1:migrate:local
npm run devเกิดอะไรขึ้นกับ D1 local
คำสั่ง npm run d1:migrate:local เรียก Wrangler พร้อม flag --local จึงสร้างหรืออัปเดตฐานข้อมูลจำลองในโฟลเดอร์ .wrangler/state ข้อมูลชุดนี้ใช้สำหรับทดสอบบนเครื่องเท่านั้น
เกิดอะไรขึ้นกับ Pages dev
npm run dev เรียก wrangler pages dev ซึ่งอ่าน [assets].directory และ D1 binding จาก wrangler.toml แล้วเปิด server ที่ port 8788
รันแบบ HTTPS local เมื่อจำเป็น
หากต้องการทดสอบ flow ที่ต้องใช้ HTTPS ให้ส่ง flag --local-protocol=https เพิ่มได้ Wrangler จะใช้ self-signed certificate สำหรับการพัฒนาในเครื่อง
npx wrangler pages dev --local-protocol=https--local = ฐานข้อมูลจำลองในเครื่อง, --remote = ฐานข้อมูลบน Cloudflare จริง, ไม่มี flag = ตรวจสอบตามคำสั่งและ context ของ Wrangler ดังนั้นสำหรับ migration ให้ระบุ flag ให้ชัดทุกครั้ง
Prove it works
ทดสอบหน้าเว็บและ API
เมื่อ server ทำงาน ให้เปิดหน้าเว็บและตรวจ response ของ API อย่างน้อยตามชุดด้านล่าง ถ้าหน้าเว็บโหลดได้แต่ API ตอบ 503 ให้กลับไปตรวจ D1 binding ชื่อ DB
http://localhost:8788/ควรเห็นหน้า login ของ Tara Bangkok Riverside HotelGET /api/configควรได้ JSON และไม่เปิดเผย LINE tokenGET /api/inventoryควรเห็นข้อมูล seed จาก schema.sqlcurl http://localhost:8788/api/config
curl http://localhost:8788/api/inventory
curl -X POST http://localhost:8788/api/auth/login \\
-H "Content-Type: application/json" \\
--data '{"lineUserId":"U_ADMIN_9999"}'{
"success": true,
"config": {
"systemName": "ระบบแจ้งซ่อมและบริหารงานวิศวกรรม",
"liffId": "2011217041-5wzVShox",
"lowStockAutoAlert": true
}
}กรณีไม่มี D1 binding ระบบจะแจ้ง HTTP 503 พร้อมข้อความให้ผูก binding ชื่อ DB แทนการตอบ success ปลอม
Production path
นำ schema ขึ้น Remote D1 และ Deploy
หลังจาก local smoke test ผ่านแล้วจึงค่อย migrate ไป D1 remote และ deploy Pages โดยแยกการตั้ง secret ออกจาก source code เสมอ โครงการนี้รวมไฟล์ Apps Script ไว้ในโฟลเดอร์ google-apps-script/Code.gs สำหรับเชื่อม Google Sheet แล้ว
ตรวจชื่อ database, Pages project และ SQL ให้ถูกต้องก่อนรัน --remote โดยเฉพาะในโครงการที่มีข้อมูลการแจ้งซ่อม production อยู่แล้ว
เช็กโครงสร้างและ syntax ก่อนส่งขึ้นระบบ
เพิ่มตารางเวรช่างและอัปเดตชื่อระบบโดยไม่ทับข้อมูลเดิม
รับ token ผ่าน prompt ไม่เขียนลงไฟล์
ใช้ URL ของ Apps Script Web App และ secret เดียวกับ Script Properties
npx wrangler pages secret put GOOGLE_SHEET_WEBHOOK_SECRET --project-name hotel-repair-pages
ส่งทั้ง static assets และ Pages Functions
npm run deploy:incremental:remotemigrations/ ก่อน แล้วจึงเรียก build และ Pages deployตั้งค่า Google Apps Script → Google Sheet
- เปิด Google Sheet ที่ต้องการใช้ แล้วเปิด Extensions → Apps Script
- คัดลอกไฟล์
google-apps-script/Code.gsจาก ZIP ฉบับนี้ไปวางแทนใน Apps Script - ตั้ง Script Properties ชื่อ
SPREADSHEET_ID,WEBHOOK_SECRETและTIMEZONE=Asia/Bangkokโดยค่าWEBHOOK_SECRETต้องตรงกับ Pages Secret - กดเรียกฟังก์ชัน
setupSheetsหนึ่งครั้งเพื่อสร้าง Tabs และหัวคอลัมน์ จากนั้น Deploy เป็น Web app โดยเลือก Execute as: Me และผู้มีลิงก์เข้าถึงได้ - นำ URL ที่ลงท้ายด้วย
/execไปตั้งเป็นGOOGLE_SHEET_WEBHOOK_URLใน Pages Secret แล้ว redeploy
URL และ secret ของ webhook ไม่ถูกบันทึกในหน้าเว็บหรือ D1 แม้หน้า Settings จะบอกสถานะ configured แล้วก็ตาม ให้ตั้งค่าจริงใน Pages Secret หรือ Cloudflare Dashboard เท่านั้น
wrangler pages deploy สำหรับโครงการนี้โครงการนี้เป็น Cloudflare Pages project มี pages_build_output_dir และ Pages Functions อยู่ในโฟลเดอร์ functions/ ให้ใช้ wrangler pages deploy หรือคำสั่ง npm ที่เตรียมไว้เท่านั้น
ค่าที่ใช้เมื่อเชื่อม Cloudflare Pages กับ Git
| Setting | ค่า | เหตุผล |
|---|---|---|
| Pages Function directory | functions/ | ให้ Pages อ่าน API handler |
| Build command | npm run build:pages | ตรวจ config และ syntax ก่อน deploy |
| Build output directory | public | ตรงกับ pages_build_output_dir |
| Deploy command | npx wrangler pages deploy public | deploy Pages assets พร้อม Functions |
If something feels off
แก้ปัญหาที่พบบ่อย
ใช้ตารางนี้แยกอาการตามชั้นของระบบ อย่าแก้ด้วยการใส่ token ลง frontend หรือสลับไปใช้ Node server เพราะ production path ของโครงการคือ Pages Functions + D1
HIGHAPI ตอบ 503: ไม่พบ D1 binding ชื่อ DB⌄
เปิด Pages project → Settings → Bindings ตรวจว่า D1 binding ใช้ variable name เป็น DB และเลือก database ถูกตัว จากนั้น redeploy หากรัน local ให้ตรวจ wrangler.toml และรัน npm run d1:migrate:local อีกครั้ง
HIGHWrangler แจ้ง Missing entry-point⌄
หากเห็น error นี้ แสดงว่าเรียกคำสั่ง Worker ในโครงการ Pages ให้กด Ctrl+C แล้วใช้ npx wrangler pages deploy public --project-name hotel-repair-pages หรือ npm run deploy:pages
MEDหน้าเว็บขึ้น แต่ข้อมูล inventory ว่าง⌄
ตรวจว่า migrate ไป environment เดียวกับที่กำลังรันหรือไม่: local ใช้ --local, production ใช้ --remote ตรวจผลด้วย GET /api/inventory และยืนยัน D1 ID ใน binding
MEDdeploy ไป Pages project ใหม่⌄
ค่า name ใน wrangler.toml ไม่ตรงกับ Pages project เดิม ให้แก้เป็นชื่อจริง หรือใช้ CF_PAGES_PROJECT=ชื่อจริง ./deploy-pages-cloudflare.sh เมื่อ deploy ด้วย Bash script
LOWIdentity เปิดไม่ได้บน local HTTP⌄
ใช้ npx wrangler pages dev public --local-protocol=https สำหรับการทดลองในเครื่อง และ production ต้องใช้ HTTPS URL ของ Pages ที่ลงทะเบียนใน LINE Developers
HIGHเปลี่ยน secret แล้วระบบยังใช้ค่าเดิม⌄
ตั้ง secret ให้กับ Pages project และ environment ที่ถูกต้อง แล้วสร้าง deployment ใหม่ ตรวจว่าไม่ได้ใส่ token ไว้ใน schema.sql, public/js/app.js หรือ localStorage ของ browser เดิม
Ship with confidence
Production checklist
ติ๊กแต่ละข้อหลังตรวจสอบแล้ว สถานะจะถูกจำไว้ใน browser เครื่องนี้เพื่อให้กลับมาเช็กต่อได้
Official sources
เอกสารอ้างอิง
เนื้อหาหลักในคู่มือนี้อิงจากเอกสาร Cloudflare ทางการและการตั้งค่าจริงของโครงการ
- Cloudflare D1 — Getting startedการสร้าง database และ execute SQL
- Cloudflare D1 — Local developmentความแตกต่างระหว่าง local และ remote database
- Cloudflare Pages — Local developmentการรัน
wrangler pages devและ port local - Cloudflare Pages — Static assets and bindingsการผูก D1 ผ่าน Dashboard หรือ Wrangler
- Cloudflare Pages — Static assetsassets.directory และ source of truth ของ config