ข้ามไปยังเนื้อหา

PWA กับ Astro: ภาพรวม

Astro เป็น framework ที่เน้น static เป็นหลัก ค่าเริ่มต้นคือการ build ไซต์ออกมาเป็น HTML, CSS และ JavaScript ล้วน ๆ โดยไม่ต้องมี server ขณะ runtime นั่นคือสิ่งที่ Progressive Web App ต้องการพอดี: ชุดของ static assets ที่แคชได้และให้บริการออฟไลน์ได้

สะพานเชื่อมระหว่าง build output ของ Astro กับฟีเจอร์ PWA คือ @vite-pwa/astro เป็น Astro integration ที่บาง ๆ ซึ่งครอบ vite-plugin-pwa ไว้ แล้ว vite-plugin-pwa ก็ใช้ Workbox ภายใต้ฝาปิดอีกทีหนึ่ง เมื่อคุณรัน astro build integration จะทำงานอัตโนมัติ:

  1. สร้าง sw.js service worker ที่ precache output แบบ static ทั้งหมด
  2. สร้าง manifest.webmanifest เพื่อบอก browser ว่าไซต์ของคุณติดตั้งได้
  3. ฉีด registration script เพื่อให้ SW ทำงานตั้งแต่โหลดครั้งแรก

islands architecture ของ Astro ช่วยให้คุณแทรก interactive components (React, Preact, Svelte, Vue, Solid…) เข้าไปในหน้า static ทั่วไปด้วย directive client:*:

src/pages/index.astro
---
import Counter from '../components/Counter.tsx';
---
<h1>ยินดีต้อนรับ</h1>
<Counter client:visible />

จากมุมมองของ service worker นั้น islands คือไฟล์ JavaScript เท่านั้น SW จะ precache ไฟล์เหล่านี้ควบคู่กับ HTML และ CSS เมื่อผู้ใช้ออฟไลน์:

  • หน้า HTML แบบ static จะถูกให้บริการจากแคชทันที
  • JS bundle ของ island ก็ถูกแคชด้วย ดังนั้น interactive components จะ hydrate ได้ตามปกติ
  • island ที่ใช้ client:load, client:visible หรือ client:idle ทำงานออฟไลน์ได้ ตราบใดที่ข้อมูลที่ต้องการพร้อมใช้งาน

@vite-pwa/astro รองรับทั้งสอง strategy ของ Workbox:

astro.config.mjs
import { defineConfig } from 'astro/config';
import AstroPWA from '@vite-pwa/astro';
export default defineConfig({
integrations: [
AstroPWA({
// 'generateSW' (ค่าเริ่มต้น): Workbox เขียน SW ให้คุณ
// 'injectManifest': คุณเขียน SW เอง แล้ว Workbox ฉีด precache list ให้
strategies: 'generateSW',
registerType: 'autoUpdate',
}),
],
});

ใช้ generateSW เมื่อต้องการ offline support โดยไม่ต้องเขียน boilerplate เลย เปลี่ยนไปใช้ injectManifest เมื่อต้องการ fetch logic แบบกำหนดเอง เช่น runtime caching strategy สำหรับ API call ที่ island ทำ

Astro รองรับทั้ง SSG (static site generation ค่าเริ่มต้น) และ SSR (server-side rendering ผ่าน adapter) การรองรับ PWA เป็นธรรมชาติที่สุดเมื่อใช้ SSG:

โหมดSW precachingหมายเหตุ
SSGPrecache เต็มรูปแบบสำหรับทุกหน้าและ assetsเหมาะที่สุดสำหรับ PWA — ทุกอย่างรู้ล่วงหน้าตอน build time
SSRPrecache เฉพาะ app shell และ static assetsDynamic routes ต้องใช้ runtime caching strategies

โมดูลนี้พาคุณจากศูนย์ไปสู่ Astro PWA ที่ทำงานออฟไลน์ได้เต็มรูปแบบใน 5 บทเรียน:

บทเรียนสิ่งที่คุณจะได้เรียนรู้
1. ภาพรวม (หน้านี้)@vite-pwa/astro ทำงานอย่างไร และโต้ตอบกับ build ของ Astro อย่างไร
2. การติดตั้งติดตั้งและเชื่อม @vite-pwa/astro เข้ากับโปรเจกต์ Astro ใหม่หรือที่มีอยู่แล้ว
3. การตั้งค่า manifestกำหนด manifest.webmanifest — ชื่อ, icon, display, theme color
4. SW strategiesเลือกและปรับแต่ง Workbox caching strategies สำหรับหน้า, assets, และ API call
5. ข้อพิเศษของ AstroIslands hydration ออฟไลน์, partial SSR, และ edge cases

แต่ละบทเรียนเป็นอิสระต่อกัน: ข้ามไปบทเรียนใดก็ได้ตามต้องการ

flowchart LR
  A["Source Files\n(.astro, .tsx, .css)"] -->|"astro build"| B["dist/\n(static HTML + assets)"]
  B --> C["@vite-pwa/astro\n(Workbox)"]
  C --> D["sw.js"]
  C --> E["manifest.webmanifest"]
  D --> F["Browser\n(installs SW, precaches dist/)"]
  E --> F
Astro build → service worker + manifest → browser
@vite-pwa/astro ครอบ package ใดไว้ภายใต้ฝาปิด?
strategy generateSW ใน @vite-pwa/astro ทำอะไร?
ใน Astro SSG build service worker จะ precache อะไรบ้าง?
โหมด output ใดของ Astro เหมาะที่สุดสำหรับ PWA precaching แบบเต็มรูปแบบ?