Deployment & Ecosystem
production build
หัวข้อที่มีชื่อว่า “production build”astro build สร้าง output ที่ deploy ได้ใน dist/ สิ่งที่อยู่ในนั้นขึ้นกับ rendering mode:
- Static —
dist/เป็นโฟลเดอร์ของไฟล์.html, CSS และ island JavaScript เป็นแค่ไฟล์ - On-demand / hybrid —
dist/มี server entry ในรูปแบบที่ adapter ของคุณ target ด้วย (Cloudflare Worker, Node server, serverless function) พร้อม static asset
ต่อ type-checking เข้ากับ build เพื่อให้ type error หยุด deploy ที่ไม่ดี: astro check && astro build
deploy สองแบบ
หัวข้อที่มีชื่อว่า “deploy สองแบบ”การตัดสินใจ deploy ที่ใหญ่ที่สุดคือ static vs on-demand — ตัวเลือกนี้กำหนดว่าคุณ host ที่ไหน ได้:
| Static | On-demand (SSR) | |
|---|---|---|
| Output | ไฟล์ HTML | server entry + assets |
| ต้องการ | static host / CDN อะไรก็ได้ | runtime (ผ่าน adapter) |
| Host | Cloudflare Pages, Netlify, GitHub Pages, S3, CDN อะไรก็ได้ | Cloudflare Workers, Node server, Vercel, Netlify Functions |
| เหมาะกับ | content ที่เหมือนกันสำหรับทุกคน | ข้อมูลต่อ request: auth, form, live data |
| Adapter | ไม่ต้อง | ต้อง |
เว็บ static ล้วน deploy ที่ไหนก็ได้ที่ serve ไฟล์ พอมี route ไหนเป็น on-demand (หรือใช้ server island หรือ Actions) คุณต้องตั้ง adapter ที่ตรงกัน — deploy โดยไม่มี adapter ก็เจอ error คลาสสิก “an adapter is required”
flowchart TB build["astro build"] --> static["Static: HTML files"] build --> ssr["On-demand: server entry + assets"] static --> cdn["any CDN / static host"] ssr --> runtime["adapter runtime: Workers, Node, serverless"]
adapter ปัจจุบัน และสองโหมดของ Cloudflare
หัวข้อที่มีชื่อว่า “adapter ปัจจุบัน และสองโหมดของ Cloudflare”version ล่าสุดของ adapter ทางการทุกตัว verify ด้วย npm view <pkg> version กับ npm registry จริง (ไม่ใช่จำจาก changelog):
| Adapter | Package | Version ล่าสุด |
|---|---|---|
| Node | @astrojs/node |
11.1.6 |
| Cloudflare | @astrojs/cloudflare |
14.3.3 |
| Vercel | @astrojs/vercel |
11.0.11 |
| Netlify | @astrojs/netlify |
8.2.6 |
Cloudflare น่าสนใจเป็นพิเศษเพราะครอบคลุมเป้าหมาย deploy ทั้งสองแบบที่บทนี้พูดถึง จาก package เดียว: เว็บ Astro ที่ static ล้วนสามารถ deploy ไป Cloudflare Pages/Workers เป็น static asset โดยไม่ต้องมี adapter เลย (แค่ไฟล์ serve จาก CDN ของ Cloudflare); พอมี route ไหนต้องการ on-demand rendering adapter: cloudflare() เปลี่ยนโปรเจกต์ เดียวกันนั้นเอง ให้กลายเป็น Cloudflare Worker ที่รัน server code ต่อ request — adapter คือสิ่งที่เพิ่ม “assets” binding กับ worker entry (dist/_worker.js/index.js) เข้าไปใน Cloudflare deploy config ไม่ใช่สิ่งที่ static-only deploy ต้องการ
ข้อจำกัดจริงของ astro preview
หัวข้อที่มีชื่อว่า “ข้อจำกัดจริงของ astro preview”astro preview เปิด local server ให้ build output ของคุณ — แต่มันจะรัน route แบบ on-demand ได้จริงหรือเปล่าขึ้นกับว่า adapter ที่คุณใช้ ship preview server ของตัวเองหรือเปล่า อ้างตรง ๆ จาก reference ของ Astro เอง: “If an adapter is set in the configuration, the preview server is provided by the adapter. Adapters are not required to provide a preview server, so this feature may not be available depending on your adapter of choice.” verify ตรง ๆ จาก exports map ของแต่ละ adapter ที่ publish จริง:
| Adapter | Ship preview entrypoint ไหม? |
|---|---|
@astrojs/node |
มี (./preview.js) |
@astrojs/cloudflare |
มี (./entrypoints/preview) |
@astrojs/vercel |
ไม่มี |
@astrojs/netlify |
ไม่มี |
บน Vercel หรือ Netlify astro preview ยังรันได้ แต่ serve ได้แค่ส่วน static ของ build — ไม่มี preview local ของ route on-demand สำหรับสองตัวนี้ โดยการออกแบบ ต้อง preview ด้วย local dev tool ของ platform เอง (vercel dev, netlify dev) แทน astro preview ยังบอกตรง ๆ ด้วยว่า “is not designed to be run in production” ไม่ว่า adapter ไหน
ตั้ง site และ base ให้ถูก
หัวข้อที่มีชื่อว่า “ตั้ง site และ base ให้ถูก”สอง config value ที่มักทำคนสะดุดตอน deploy:
siteต้องเป็น URL ที่ deploy จริง (เช่นhttps://example.com) sitemap, canonical tag และ RSS สร้าง absolute URL จากค่านี้ —siteผิด link ก็ผิดbaseต้องตรงกับ subpath ที่คุณถูก serve deploy ไปexample.com/docs/ก็ตั้งbase: '/docs'แล้วอ้าง internal link ด้วย base prefix serve ที่ domain root ก็ละไว้baseที่ไม่ตรงเป็นสาเหตุปกติของ “CSS และ link ของเว็บที่ deploy 404 หมด” — asset ถูกหาที่ path ผิด
ecosystem
หัวข้อที่มีชื่อว่า “ecosystem”Astro เป็น content-first และ ecosystem ของตัวเองสะท้อนสิ่งนั้น:
- Starlight — documentation-site framework ทางการที่สร้างบน Astro (คอร์สนี้ก็สร้างด้วย Starlight): sidebar, search, i18n และ dark mode มาในตัว
- Integrations directory — catalog ขนาดใหญ่ของ integration ทางการและ community: UI framework, CMS connector, image service, analytics และ adapter สำหรับ host หลักทุกตัว
- content-focused patterns — เมื่อรวมกับ content collection Astro เป็นตัวเลือกที่เหมาะสำหรับ blog, docs, marketing site และ headless-CMS front-end ที่คุณได้เว็บ static (หรือ on-demand) ที่เร็วพร้อม content ที่มี type
มี package สองตัวที่ควรระวังเป็นพิเศษ ทั้งคู่ verify ตรง ๆ จาก npm metadata จริง ไม่ใช่ความจำจาก blog post:
@astrojs/db—npm view @astrojs/db deprecatedคืนค่า: “This package is deprecated. Use a database client (Drizzle, Kysely, etc.) directly instead.” ใช้node:sqlite, Drizzle หรือ database แบบ hosted (Turso, Neon, PlanetScale) แทนastro-integration-kit— ก็ npm deprecate เหมือนกัน (npm view astro-integration-kit deprecatedชี้ไปที่ migration guide ของตัวเอง) ถ้า snippet ที่ AI generate มาใช้มันเพื่อสร้าง integration เอง เช็คก่อนว่า helper ที่มันใช้ย้ายเข้า Astro core แล้วหรือยัง ก่อนจะเพิ่ม dependency ใหม่
หยิบ framework อย่าง Starlight เมื่อตรงกับ use case ของคุณ แทนที่จะสร้าง docs infrastructure ใหม่ด้วยมือ — สัญชาตญาณ “compose อย่าสร้างใหม่” เดียวกันที่ไหลผ่าน Astro
อัปเกรดจาก Astro 6 เป็น 7
หัวข้อที่มีชื่อว่า “อัปเกรดจาก Astro 6 เป็น 7”โปรเจกต์ส่วนใหญ่อัปเกรดได้ในบ่ายเดียว checklist มีดังนี้:
- Node 22.12+ เป็นขั้นต่ำ (เท่ากับ Astro 6) รัน
npx @astrojs/upgradeเพื่อ bumpastroและ integration@astrojs/*ทุกตัวพร้อมกัน - ถอด experimental flag ที่ stable แล้ว:
experimental.cache,experimental.routeRules,experimental.loggerย้ายไปเป็นcache,routeRules,loggerระดับบนสุด ส่วนexperimental.rustCompiler,queuedRendering,advancedRoutingลบทิ้ง (เป็น default แล้ว) - แก้สิ่งที่ Rust compiler ปฏิเสธ: tag ที่ไม่ปิดและการซ้อนที่ผิดเป็น build error แล้ว error message ชี้ไฟล์และบรรทัดให้
- เช็ก whitespace:
compressHTMLdefault เป็น'jsx'ใส่{" "}ตรงที่ inline element ต้องมีช่องว่าง หรือตั้งcompressHTML: trueชั่วคราว - Markdown plugin: ถ้าใช้ remark/rehype plugin ให้ติดตั้ง
@astrojs/markdown-remarkและตั้งmarkdown: { processor: unified() }ถ้าไม่ใช้ก็รับความเร็วของ Sätteri ไปเลย - Vite 8: ทบทวน migration note ของ Vite 8 สำหรับ plugin เฉพาะของ Vite ที่ตั้งไว้ใต้ key
vite - เปลี่ยนชื่อ
src/fetch.tsถ้าคุณมีไฟล์ชื่อนี้ที่ไม่เกี่ยวกัน (หรือตั้งfetchFile) - API ที่ถูกถอด:
@astrojs/db(เปลี่ยนไปnode:sqlite, Drizzle หรือ DB แบบ hosted), ค่าคงที่ event ของastro:transitions(ใช้ชื่อ event แบบ string เช่น'astro:before-preparation') และgetContainerRendererตอนนี้ import จาก subpath ที่เจาะจงกับ framework (@astrojs/preact/container-rendererถ้าใช้ Preact — subpath ตรงกับ package@astrojs/<framework>ที่โปรเจกต์ติดตั้งจริง verify แล้วในบท testing)
จากนั้น astro check && astro build — build เร็วขึ้นอย่างเห็นได้ชัด ซึ่งคือรางวัล
อ่านโค้ดที่ AI เขียน
หัวข้อที่มีชื่อว่า “อ่านโค้ดที่ AI เขียน”คำตอบ “นี่คือวิธี deploy Astro” ที่ AI generate มา ควรเช็คกับสิ่งที่เป็นจริงจริง ๆ บน 7.3.5:
- มันบอกว่า adapter เป็น optional สำหรับ server island หรือ Actions บนเว็บที่ static ล้วนหรือเปล่า? พิสูจน์แล้วข้างบน (และในบท rendering-modes): feature พวกนั้นต้องมี on-demand rendering ถึงจะรันได้เลย ซึ่งต้องมี adapter แม้ว่าทุก page route จะ prerender ก็ตาม
- มันแนะนำ
@astrojs/dbหรือastro-integration-kitโดยไม่มีคำเตือนหรือเปล่า? ทั้งคู่ npm deprecate แล้ว — พิสูจน์แล้วข้างบนด้วยประกาศ deprecation จริง ไม่ใช่การเดาว่าไม่ค่อยมีคนใช้ - มันอ้างว่า
astro previewเป็น production server แบบเบา ๆ ที่ใช้ได้จริงหรือเปล่า? พิสูจน์แล้วข้างบนด้วยคำพูดของ CLI เอง: “not designed to be run in production” - มันสมมติว่า
astro previewทดสอบ route on-demand ได้เหมือนกันหมดไม่ว่า adapter ไหนหรือเปล่า? พิสูจน์แล้วข้างบน: มีแค่ Node กับ Cloudflare ที่ ship preview entrypoint; Vercel กับ Netlify ไม่มี ดังนั้นastro previewserve ได้แค่ static output บนสองตัวนั้น - มันแนะนำว่า Cloudflare ต้อง มี
adapter: cloudflare()เสมอถึงจะ deploy ได้หรือเปล่า? เว็บ static ล้วน deploy ไป Cloudflare Pages/Workers เป็น static asset ได้โดยไม่ต้องมี adapter เลย — adapter มีไว้เฉพาะ on-demand rendering พิสูจน์แล้วข้างบน
🐛 หา bug ในโค้ดนี้
import { defineConfig } from 'astro/config';import vercel from '@astrojs/vercel';
export default defineConfig({adapter: vercel(),});เฉลย
ตรงนี้ไม่มี config error เลย — แต่ทีมที่พึ่งพา astro preview ในการ verify route on-demand ด้วยมือก่อน deploy ไป Vercel กำลังเชื่อ step ที่ พิสูจน์แล้วข้างบน ไม่ได้รัน route นั้นจริง ๆ: exports ของ package @astrojs/vercel ไม่มี preview entrypoint เลย ดังนั้น astro preview บน config นี้ serve ได้แค่ส่วน static ของ build เท่านั้น วิธีแก้ไม่ใช่การแก้โค้ดในไฟล์นี้ — แต่เป็นเรื่อง process: ใช้ vercel dev (หรือ deploy ไป Vercel preview environment จริง) เพื่อทดสอบ route on-demand จริง ๆ ก่อน ship เพราะ astro preview ทำไม่ได้เงียบ ๆ
Mental Model
หัวข้อที่มีชื่อว่า “Mental Model”deploy target จริง ๆ คือสองคำถามแยกกันที่ Astro ตอบเป็นอิสระจากกัน: “ไฟล์ไปอยู่ที่ไหน” (static host อะไรก็ได้ สำหรับ HTML/CSS/JS ที่ dist/client ผลิต) กับ “ใครรัน server code” (adapter ที่แปล on-demand rendering ของ Astro เป็น runtime shape ของ platform นั้นเจาะจง) Cloudflare ที่ตอบทั้งสองคำถาม — static asset ล้วน ๆ หรือ Worker จาก package เดียวกัน — คือภาพที่ชัดที่สุดว่านี่เป็นสองแกนที่แยกกันจริง ๆ ไม่ใช่การตัดสินใจ “hosting provider” เดียวรวมกัน
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| Deploy แบบ static | Deploy แบบ on-demand | |
|---|---|---|
| ต้องมี adapter ไหม | ไม่ต้อง | ต้อง |
| Host | CDN/static host อะไรก็ได้ รวมถึง Cloudflare Pages โดยไม่ต้องมี adapter | Cloudflare Workers, Node, Vercel, Netlify Functions |
astro preview ทดสอบได้จริง local ไหม |
ได้เสมอ | เฉพาะ adapter ที่ ship preview entrypoint (Node, Cloudflare — พิสูจน์แล้วข้างบน; ไม่ใช่ Vercel/Netlify) |
| เหมาะกับ | content ที่เหมือนกันสำหรับทุกคน | auth, form, ข้อมูล live/request-time |
ความเข้าใจผิดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ความเข้าใจผิดที่พบบ่อย”- “
astro previewเป็นวิธี smoke-test production build ก่อน deploy ที่ใช้ได้ดี ไม่ว่า adapter ไหน” พิสูจน์แล้วข้างบน: บน Vercel กับ Netlify โดยเฉพาะ มันรัน route on-demand ไม่ได้เลย — ได้แค่ส่วน static เท่านั้น มันยังบอกตรง ๆ ด้วยว่าไม่ได้ตั้งใจให้รับ production traffic ไม่ว่า adapter ไหน - “deploy ไป Cloudflare ต้องมี
adapter: cloudflare()เสมอ” เว็บ static ล้วน deploy ไป Cloudflare เป็น static asset ธรรมดาโดยไม่ต้องมี adapter เลย — adapter มีไว้แค่สำหรับ on-demand rendering บน platform เดียวกันนั้น - “
@astrojs/dbแค่ไม่ค่อยมีคนใช้เท่า Drizzle ไม่ได้ deprecate จริง” พิสูจน์แล้วข้างบนด้วยประกาศ deprecation จริงบนตัว package เอง - “อัปเกรด Astro 6 → 7 ส่วนใหญ่คือแก้โค้ดของตัวเอง” ส่วนใหญ่ของ checklist ข้างบนคือการลบสิ่งที่ไม่มีอยู่แล้ว (
experimentalflag, ค่าคงที่astro:transitions) มากกว่าจะเป็นการแก้ bug ในโค้ดของคุณเอง