Offline และ App Shell
“ทำงานแบบ offline” หมายความว่าอะไร?
หัวข้อที่มีชื่อว่า ““ทำงานแบบ offline” หมายความว่าอะไร?”เมื่อผู้ใช้เปิดแอปโดยไม่มีอินเทอร์เน็ต browser จะยังต้องมีบางอย่างแสดงผล หากไม่มีกลยุทธ์ offline เลย Chrome จะแสดง offline dinosaur ที่โด่งดัง Firefox แสดง “Server not found” และ Safari จะหน้าจอว่างเปล่า PWA สามารถทำได้ดีกว่านั้น
“ทำงานแบบ offline” ไม่ได้แปลว่าทุกฟีเจอร์จะใช้งานได้โดยไม่มีเครือข่าย แต่หมายความว่าผู้ใช้จะเห็น UI ที่มีความหมายและใช้งานได้ แทนที่จะเป็นหน้า error ของ browser ขึ้นอยู่กับแอปของคุณ อาจหมายความว่า:
- แอปอ่านข่าวที่แสดงบทความที่ดึงมาล่าสุด
- รายการสิ่งที่ต้องทำที่ให้ผู้ใช้สร้างรายการและซิงค์เมื่อมีการเชื่อมต่อกลับ
- แอปแผนที่ที่แสดงชุดไทล์ที่แคชสำหรับเมืองที่ผู้ใช้เคยเข้าชมก่อนหน้า
- อย่างน้อยก็ shell page ที่อธิบายว่าผู้ใช้ offline อยู่และยังคง branding ไว้
สิ่งที่เหมือนกันคือ browser ไม่ต้องรับผิดชอบต่อการเชื่อมต่อแต่เพียงผู้เดียว — service worker ต่างหากที่รับผิดชอบ
ทำไมเครือข่ายถึงไม่เพียงพอ
หัวข้อที่มีชื่อว่า “ทำไมเครือข่ายถึงไม่เพียงพอ”หน้าเว็บแบบดั้งเดิมพึ่งพาเครือข่ายทุกไบต์: HTML, CSS, JavaScript, รูปภาพ การขาดการเชื่อมต่อเพียงครั้งเดียวหมายความว่าไม่มีอะไรโหลดได้ Service workers ทำลายการพึ่งพานี้โดยทำหน้าที่เป็น programmable proxy ที่สามารถให้บริการ assets จาก cache ในเครื่อง
App-shell model
หัวข้อที่มีชื่อว่า “App-shell model”App shell คือชุดขั้นต่ำของ HTML, CSS, และ JavaScript ที่จำเป็นสำหรับการ render โครงของแอป — navigation bar, sidebar, loading skeleton, และ chrome อื่น ๆ ที่เหมือนกันในทุกหน้า shell เปลี่ยนแปลงน้อยมาก (คิดว่า: ครั้งต่อ deployment) และมักมีขนาดเล็ก
Dynamic content — ข้อมูลจริงที่แอปแสดง — โหลดแยกกัน มักมาจาก API หรือ IndexedDB เนื้อหานี้เปลี่ยนแปลงตลอดเวลาและไม่สามารถ precache ได้ทั้งหมด
แนวคิดนั้นเรียบง่าย: cache shell ครั้งเดียว โหลดได้ทันทีในทุกการเข้าชม แล้วดึงเฉพาะ content เท่านั้น
การเข้าชมครั้งแรก vs ครั้งถัดไป
หัวข้อที่มีชื่อว่า “การเข้าชมครั้งแรก vs ครั้งถัดไป”ใน การเข้าชมครั้งแรก browser ยังไม่มี cache ดังนั้นทุกอย่างมาจากเครือข่าย Service worker ติดตั้งในพื้นหลังและเติมข้อมูล cache ด้วย shell assets
ใน ทุกการเข้าชมถัดไป (รวมถึงเมื่อ offline) service worker จะดักจับ navigation request และตอบกลับจาก cache Shell ปรากฏขึ้นทันที — โดยปกติน้อยกว่า 100 ms — ขณะที่แอป fetch เนื้อหาใหม่แบบ asynchronous
flowchart TD
subgraph CacheStorage["Cache Storage (precached on install)"]
A[index.html]
B[app.css]
C[app.js]
end
subgraph Network["Network / IndexedDB"]
D[Article data]
E[User profile]
F[Product listings]
end
V[Browser visits URL]
SW[Service Worker]
V --> SW
SW -->|"cache hit — instant"| CacheStorage
CacheStorage -->|"shell rendered"| R[Page visible]
R -->|"runtime fetch"| Network
Network -->|"fill in data"| R ประสิทธิภาพที่ได้รับ
หัวข้อที่มีชื่อว่า “ประสิทธิภาพที่ได้รับ”นอกจากการรองรับ offline แล้ว การ cache shell ยังให้ประสิทธิภาพที่วัดได้:
- Time to First Byte (TTFB) สำหรับ shell ลดลงเกือบเป็นศูนย์ — response มาจาก local storage ไม่ใช่ server
- Cumulative Layout Shift (CLS) ลดลงเพราะ layout ของ shell อยู่ในตำแหน่งแล้วก่อนที่ dynamic content จะมาถึง
- การเข้าชมซ้ำ รู้สึกทันทีแม้บนการเชื่อมต่อช้า เพราะ navigation ไม่ต้องรอเครือข่ายอีกต่อไป
เมื่อไม่ควรใช้ app-shell model
หัวข้อที่มีชื่อว่า “เมื่อไม่ควรใช้ app-shell model”รูปแบบ app-shell ทำงานได้ดีที่สุดสำหรับ Single Page Applications (SPAs) และไซต์ที่มี layout ทั่วไปครอบทุกหน้า เหมาะน้อยกว่าสำหรับ:
- ไซต์ที่เน้นเนื้อหาที่ทุก URL มีโครงสร้าง HTML เฉพาะ
- ไซต์ที่ shell มีขนาดใหญ่ (หลาย MB) — ค่าใช้จ่ายของ precache มากกว่าประโยชน์
- แอปที่ต้องแสดงข้อมูลล่าสุดที่สุดเสมอสำหรับทุก pixel