ข้อควรพิจารณาเฉพาะของ Astro
ข้อควรพิจารณาเฉพาะของ Astro สำหรับ PWA
หัวข้อที่มีชื่อว่า “ข้อควรพิจารณาเฉพาะของ Astro สำหรับ PWA”ความยืดหยุ่นของ Astro ที่รองรับทั้ง static, SSR และ hybrid rendering นำมาซึ่งการตัดสินใจสำคัญหลายข้อที่ส่งผลโดยตรงต่อพฤติกรรมของ service worker การทำความเข้าใจเรื่องเหล่านี้จะช่วยให้ผู้ใช้ได้รับประสบการณ์ offline ที่รวดเร็วและเชื่อถือได้
SSG vs SSR/hybrid: อะไรถูก precache บ้าง
หัวข้อที่มีชื่อว่า “SSG vs SSR/hybrid: อะไรถูก precache บ้าง”โหมด output เริ่มต้นของ Astro คือ static ซึ่งจะ render ทุกหน้าเป็นไฟล์ .html ในช่วง build time ทำให้ @vite-pwa/astro สามารถสแกนโฟลเดอร์ dist/ และนำทุกไฟล์ HTML เข้า precache manifest ได้โดยอัตโนมัติ
เมื่อเปลี่ยนเป็น output: 'server' หรือ output: 'hybrid' สถานการณ์จะเปลี่ยนไป เนื่องจาก SSR routes ถูก generate บน server เมื่อมีการร้องขอ จึงไม่มีไฟล์ .html ให้ Workbox hash และ precache ได้ routes เหล่านั้นต้องใช้ runtime caching แทน
// astro.config.mjs — SSG (default), all pages precachedAstroPWA({ registerType: 'autoUpdate', workbox: { globPatterns: ['**/*.{css,js,html,svg,png,ico}'], // Every /blog/*, /about, / etc. is a static file — precached },})// astro.config.mjs — hybrid SSR// output: 'hybrid' or 'server'AstroPWA({ registerType: 'autoUpdate', workbox: { globPatterns: ['**/*.{css,js,svg,png,ico}'], // assets only — no .html for SSR routes runtimeCaching: [ { urlPattern: ({ url }) => url.pathname.startsWith('/api/'), handler: 'NetworkFirst', options: { cacheName: 'api-cache', networkTimeoutSeconds: 3 }, }, ], },})ตารางอ้างอิงเร็ว
หัวข้อที่มีชื่อว่า “ตารางอ้างอิงเร็ว”| สถานการณ์ | Precache | Runtime cache |
|---|---|---|
SSG page (output: 'static') | ใช่ (อัตโนมัติ) | ไม่จำเป็น |
SSR page (output: 'server') | ไม่ | จำเป็น |
| Static asset (CSS/JS/images) | ใช่ | ไม่ |
| External API | ไม่ | จำเป็น |
การจัดแนว base path กับ scope
หัวข้อที่มีชื่อว่า “การจัดแนว base path กับ scope”เมื่อ deploy Astro ไปยัง sub-path เช่น GitHub Pages ที่ /my-app/ scope ของ service worker จะต้องตรงกับ base นั้น หาก scope เป็น / แต่แอปอยู่ที่ /my-app/ SW จะไม่สามารถควบคุมหน้าของคุณได้
ตั้งค่า base, scope, manifest.start_url และ root ของ Workbox globPatterns ให้สอดคล้องกัน:
// astro.config.mjs — deployed at /my-app/export default defineConfig({ base: '/my-app/', integrations: [ AstroPWA({ scope: '/my-app/', base: '/my-app/', manifest: { start_url: '/my-app/' }, workbox: { globPatterns: ['**/*.{css,js,html,svg,png,ico}'] }, }), ],})ค่าเริ่มต้น trailingSlash ของ Astro คือ 'ignore' หมายความว่าทั้ง /about และ /about/ ใช้ได้ ให้แน่ใจว่า scope ลงท้ายด้วย slash (/my-app/) เพื่อให้ SW ควบคุม path ทั้งหมดภายใต้ prefix นั้น
islands hydration และพฤติกรรม offline
หัวข้อที่มีชื่อว่า “islands hydration และพฤติกรรม offline”Astro islands จะส่ง JavaScript ของแต่ละ component เป็น chunk แยกต่างหากใน dist/ เนื่องจาก @vite-pwa/astro precache ทุกไฟล์ที่ตรงกับ globPatterns bundle JS ของ island ทั้งหมดจึงถูก cache โดยอัตโนมัติ island ที่ใช้ client:visible หรือ client:idle จะ hydrate ได้ถูกต้องแม้ offline ตราบที่ chunk ของตัวเองอยู่ใน precache manifest ซึ่งจะเป็นเช่นนั้นหาก globPatterns ครอบคลุม **/*.js
ไม่จำเป็นต้องกำหนดค่าพิเศษสำหรับ islands offline support ข้อจำกัดสำคัญคือข้อมูลของ island ต้องพร้อมใช้งาน offline ด้วย: หาก component นั้น fetch จาก API ที่ไม่ได้ cache ไว้ขณะ runtime ข้อมูลนั้นจะหายไปเมื่อ offline
การทดสอบด้วย astro preview
หัวข้อที่มีชื่อว่า “การทดสอบด้วย astro preview”Service worker จะถูก generate เฉพาะระหว่าง astro build เท่านั้น การรัน astro dev ไม่ สร้าง SW ดังนั้น DevTools จะไม่แสดง service worker ที่ register ไว้ ให้ทดสอบ PWA กับ production build เสมอ:
# Build first, then preview — the SW only works in the built outputnpm run buildnpm run preview# Open http://localhost:4321 in DevTools > Application > Service Workersหลังเปิด preview URL ไปที่ DevTools → Application → Service Workers เพื่อยืนยันว่า SW registered และ active แล้ว ใช้ Cache Storage เพื่อตรวจสอบว่า precache manifest entries มีอยู่ครบถ้วน หากต้องการจำลองพฤติกรรม offline ให้ติ๊ก Offline ใน Network panel แล้ว reload
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| Astro SSG (precache ผลลัพธ์ build ทั้งหมด) | offline ทำงานได้ทันทีหลัง build เพราะทุกหน้าเป็น static file อยู่แล้ว | เนื้อหาที่เปลี่ยนบ่อยต้อง rebuild+redeploy ใหม่ทุกครั้งถึงจะ cache ตัวใหม่ |
| Astro + island architecture (partial hydration) | ส่ง JS ลง client น้อยกว่ามาก เหมาะกับ PWA ที่เน้นความเร็ว | ต้องระวัง service worker cache แยก JS ของแต่ละ island ให้ถูก scope |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- ลืมว่า Astro เป็น multi-page app โดย default ทำให้ navigation ระหว่างหน้าเป็น full page load ที่ service worker ต้อง handle ต่างจาก SPA
- ไม่เผื่อ cache สำหรับหน้าที่ render แบบ SSR (ถ้าใช้ hybrid mode) ทำให้ offline fallback ใช้ไม่ได้กับหน้าที่ไม่ใช่ static
- Precache ทุกหน้ารวมถึงหน้าที่แทบไม่มีคนเข้า ทำให้ storage โตเกินจำเป็นโดยไม่ได้ประโยชน์เพิ่ม
💡 ตัวอย่างจากของจริง
VitePress / Astro documentation sites — ใช้ SSG ร่วมกับ service worker precache ทำให้ documentation เปิดอ่านได้แบบ offline ทันทีหลังเข้าชมครั้งแรก
Astro blog starter ecosystem — หลายเว็บบล็อกที่ build ด้วย Astro ใช้แนวทาง precache ทั้งเว็บเพราะขนาดไฟล์เล็กพอจะทำได้จริง