Offline Fallback Page
การให้บริการหน้า offline fallback
หัวข้อที่มีชื่อว่า “การให้บริการหน้า offline fallback”การปรับปรุงที่ง่ายที่สุดที่คุณสามารถทำกับ PWA ที่ยังไม่มีกลยุทธ์ offline คือการเพิ่มหน้า offline fallback หน้าเดียว เมื่อผู้ใช้นำทางไปยังไซต์และเครือข่ายไม่พร้อมใช้งาน แทนที่จะแสดงหน้า error ของ browser พวกเขาจะเห็นหน้าที่มี branding ของคุณที่บอกว่าพวกเขา offline
รูปแบบสองขั้นตอน
หัวข้อที่มีชื่อว่า “รูปแบบสองขั้นตอน”- ใน
install— precacheoffline.htmlเพื่อให้พร้อมใช้ทันที แม้ก่อนที่ผู้ใช้จะเคยเยี่ยมชมหน้าอื่น - ใน
fetch— ดักจับ navigation requests (event.request.mode === 'navigate'), ลองเครือข่าย, และ catch ความล้มเหลวโดยให้บริการoffline.htmlที่ cache ไว้
รูปแบบนี้จงใจให้เรียบง่าย ไม่ดักจับ sub-resources (รูปภาพ, script, API calls) — เฉพาะ top-level page navigations เท่านั้น ทำให้ logic เรียบง่ายและหลีกเลี่ยงผลข้างเคียงที่ไม่ตั้งใจต่อ API calls
Precaching ใน install
หัวข้อที่มีชื่อว่า “Precaching ใน install”const OFFLINE_URL = '/offline.html';
self.addEventListener('install', (event) => { event.waitUntil( caches.open('offline-v1').then((cache) => cache.addAll([OFFLINE_URL])) ); self.skipWaiting();});event.waitUntil() ทำให้ install phase ทำงานต่อจนกว่า Promise จะ resolve เพื่อให้แน่ใจว่าไฟล์ถูก cache ก่อนที่ SW จะ activate self.skipWaiting() ทำให้ SW ใหม่เข้าควบคุมทันทีโดยไม่ต้องรออันเก่า
ดักจับ navigation requests
หัวข้อที่มีชื่อว่า “ดักจับ navigation requests”self.addEventListener('fetch', (event) => { if (event.request.mode !== 'navigate') return;
event.respondWith( fetch(event.request).catch(() => caches.match('/offline.html')) );});event.request.mode === 'navigate' เป็น true เฉพาะสำหรับ navigation requests ระดับบนสุดเท่านั้น — การคลิกลิงก์, การป้อน URL, หรือการรีเฟรชหน้า Sub-resource requests (CSS, JS, XHR) มี modes อื่น ('cors', 'no-cors', 'same-origin') ดังนั้น guard นี้จะดักจับเฉพาะ page loads เท่านั้น
การ activate และ claiming clients
หัวข้อที่มีชื่อว่า “การ activate และ claiming clients”self.addEventListener('activate', (event) => { event.waitUntil(self.clients.claim());});self.clients.claim() ทำให้ service worker เข้าควบคุมหน้าที่เปิดอยู่แล้วโดยไม่ต้องรีโหลด หากไม่มี หน้าปัจจุบันจะไม่ถูกควบคุมจนกว่าจะนำทางครั้งต่อไป
ขั้นตอนการ navigation request
หัวข้อที่มีชื่อว่า “ขั้นตอนการ navigation request”sequenceDiagram
participant U as User
participant SW as Service Worker
participant N as Network
participant C as Cache Storage
U->>SW: navigate to /page (mode: navigate)
SW->>N: fetch(request)
alt Network available
N-->>SW: 200 OK Response
SW-->>U: Page renders normally
else Network unavailable
N--xSW: fetch() rejects
SW->>C: caches.match('/offline.html')
C-->>SW: cached offline.html
SW-->>U: Offline fallback page
end ลองใช้งานจริง
หัวข้อที่มีชื่อว่า “ลองใช้งานจริง”Demo ด้านล่างลงทะเบียน service worker ที่ precaches offline.html เปิด StackBlitz preview จากนั้นใช้แท็บ Network ของ DevTools เพื่อเปลี่ยนเป็น offline mode แล้วรีโหลดหน้า — คุณควรเห็น offline fallback แทน dinosaur
สิ่งที่ควรใส่ในหน้า offline ของคุณ
หัวข้อที่มีชื่อว่า “สิ่งที่ควรใส่ในหน้า offline ของคุณ”หน้า offline fallback ที่ดีควร:
- ตรงกับ brand ของคุณ — ฟอนต์, สี, และโลโก้เดียวกับแอปที่เหลือ
- อธิบายสถานการณ์อย่างชัดเจน — “You are offline” ดีกว่า error ทั่วไป
- มีปุ่มลองใหม่ —
location.reload()เพียงพอแล้ว - เป็น self-contained อย่างสมบูรณ์ — ไม่มี external stylesheets หรือ scripts เพราะสิ่งเหล่านั้นก็จะล้มเหลวเมื่อ offline เช่นกัน
- มีขนาดเล็ก — ต่ำกว่า 5 KB แบบบีบอัดเพื่อให้ precache ได้ทันที
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| Serve หน้า offline fallback ที่ออกแบบเอง | UX ดีกว่ามาก ผู้ใช้รู้สถานะและทำอะไรต่อได้ (เช่นดูของที่ cache ไว้) | ต้องออกแบบและ maintain หน้าเพิ่มอีกหนึ่งหน้า |
| ปล่อยให้ browser แสดง error page มาตรฐาน (dino game ของ Chrome) | ไม่ต้องทำอะไรเพิ่ม | ผู้ใช้ไม่รู้ว่าแอปมีอะไรให้ใช้ offline ได้บ้าง ประสบการณ์แย่กว่ามาก |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- ไม่ precache หน้า offline fallback เอง ทำให้ตอนที่ network ล้มเหลวจริงๆ กลับโหลดหน้า fallback ไม่ได้เช่นกัน (chicken-and-egg problem)
- แสดง fallback แบบเดียวกันทุก route โดยไม่บอกผู้ใช้ว่าตอนนี้กำลังพยายามโหลดอะไรอยู่
- ลืมทดสอบ fallback บนกรณีที่ network “ช้ามาก” ไม่ใช่แค่ “ขาดหายสนิท” ทำให้ UX พังตอนเน็ตแค่แย่ไม่ถึงกับหลุด
💡 ตัวอย่างจากของจริง
Chrome dino game — เป็น offline fallback แบบ built-in ของ browser เอง ที่แสดงให้เห็นว่า “ไม่มีอะไรให้ทำ” นั้น UX แย่แค่ไหนเทียบกับแอปที่เตรียม fallback เอง
The Guardian / BBC News — แสดงหน้า offline ที่บอกชัดว่าไม่มีสัญญาณ พร้อมลิงก์ไปบทความที่เคย cache ไว้ให้อ่านต่อได้ทันที