Progressive Web App (PWA) 2026: Xây app web mượt như mobile app với offline, push notification và cache

2 tháng trước · 9 phút đọc
PWA là gì và tại sao 2026 lại quan trọng hơn bao giờ hết
Mình nhớ lần đầu demo PWA cho khách hàng. Tắt mạng, reload trang - app vẫn chạy. Khách hàng nhìn như thấy ma. "Web mà làm được vậy à?"
Đúng vậy. Progressive Web App không phải trend mới, nhưng năm 2026 là thời điểm nó thực sự mature - browser support đã đủ rộng, tooling đã ổn định, và quan trọng nhất: người dùng đã quen với việc cài app từ trình duyệt.
PWA là web app tận dụng các Web API hiện đại để có trải nghiệm gần với native app: cài được lên home screen, chạy offline, nhận push notification, load nhanh ngay cả trên mạng chậm. Không cần App Store, không cần review process, deploy xong là người dùng có bản mới ngay.
Ba trụ cột của PWA: Reliable (offline), Fast (performance), Engaging (push, install)
Con số thực tế nói lên tất cả: 65% more pages per session (PWA case study roundups). Đây không phải lý thuyết - Twitter Lite, Starbucks, MakeMyTrip đều đã chứng minh PWA có thể thay thế native app trong nhiều use case thực tế.
Decision tree: Khi nào chọn PWA, khi nào không
Đây là câu hỏi mình hay bị hỏi nhất. Câu trả lời không phải "PWA luôn tốt hơn" hay "native luôn cần thiết" - mà phụ thuộc vào context cụ thể.
Không có câu trả lời tuyệt đối - context quyết định tất cả
PWA thắng native khi:
- SME và MVP: Budget hạn chế, team nhỏ, cần ship nhanh. Một codebase chạy mọi platform thay vì maintain iOS + Android riêng.
- Cross-platform content app: Tin tức, blog, e-commerce catalog, dashboard - những app nặng về hiển thị data hơn là hardware access.
- Không muốn App Store friction: Update ngay không cần review, người dùng không cần download 50MB từ store.
- SEO quan trọng: PWA là web, Google index được. Native app không có lợi thế này.
Native app vẫn thắng khi:
- Game nặng và AR/VR: WebGL đã mạnh nhưng vẫn chưa match được native rendering pipeline cho game AAA hay AR experience phức tạp.
- Hardware access sâu: Bluetooth Low Energy, NFC writing, background location tracking liên tục, camera với custom processing - Web API vẫn còn giới hạn.
- iOS push notification (trước 2023): Apple chỉ mới hỗ trợ Web Push trên iOS 16.4+, và vẫn có một số hạn chế so với native.
- Offline storage lớn: IndexedDB có giới hạn, trong khi native app có full file system access.
Một rule of thumb mình hay dùng: nếu app của bạn chủ yếu là UI + API calls + một chút offline, PWA là đủ. Nếu app cần làm gì đó mà browser API chưa expose - đi native.
Với React dev, nếu bạn chưa vững JavaScript nâng cao, khóa Lập Trình JavaScript Nâng Cao sẽ giúp hiểu sâu hơn về event loop, Promise và async patterns - những thứ cực kỳ quan trọng khi làm việc với service worker.
Service worker và offline-first architecture
Service worker là backbone của mọi PWA. Hiểu đơn giản: nó là một JavaScript file chạy trên background thread riêng, intercept mọi network request của app bạn, và quyết định trả về từ cache hay fetch từ network.
Service worker nằm giữa browser và network, quyết định mọi request đi đâu
App Shell Model là pattern đi kèm với offline-first. Ý tưởng: tách app thành 2 phần:
- App Shell - skeleton UI (header, nav, layout) được cache vĩnh viễn, load gần như instant
- Dynamic Content - data từ API, được fetch và cache riêng theo chiến lược khác
Người dùng mở app lần đầu thấy shell hiện ngay (< 100ms), content điền vào sau. Offline thì shell vẫn hiện, content thì show cached version hoặc placeholder. Trải nghiệm mượt hơn nhiều so với blank screen.
Caching strategies với Workbox
Viết tay service worker logic cho mọi loại request rất dễ bug. Workbox - thư viện của Google - giải quyết vấn đề này bằng cách wrap sẵn các caching strategy phổ biến.
Setup Workbox với Vite:
Ba chiến lược cache phù hợp với 3 loại dữ liệu khác nhau - chọn sai là chọn bug
Ba strategy bạn sẽ dùng 90% thời gian:
Network-first: Luôn thử fetch từ network trước, fallback về cache nếu offline hoặc timeout. Dùng cho API data cần fresh nhất có thể.
Cache-first: Trả về từ cache ngay, chỉ fetch network nếu không có cache. Dùng cho ảnh, font, static assets - thứ gần như không thay đổi.
Stale-while-revalidate: Trả về cache ngay (nhanh), đồng thời fetch network để update cache cho lần sau. Trade-off: người dùng có thể thấy data cũ một lần. Dùng cho avatar, thumbnail, content ít critical.
Background sync và push notifications
Hai tính năng này là thứ làm PWA thật sự "feel like native" - không chỉ là web có offline mode.
Background sync
Scenario: người dùng điền form rồi submit khi đang offline. Thay vì báo lỗi, Background Sync queue request lại và tự động retry khi có mạng - kể cả khi app đã đóng.
Push notifications
Background sync giữ data an toàn khi offline, push notification kéo người dùng quay lại
Với push notification, bạn cần generate VAPID keys và setup server-side để gửi. Thư viện web-push cho Node.js là lựa chọn phổ biến nhất. Xem hướng dẫn setup VAPID tại đây: Hướng dẫn setup VAPID với web-push.
Install prompt và app manifest
App shell, service worker, push notification - xong hết rồi nhưng người dùng vẫn chưa "cài" app. Install prompt là cầu nối cuối cùng.
Browser tự động show install prompt khi app đáp ứng đủ tiêu chí PWA installability. Bạn có thể custom timing để tăng conversion:
Custom install prompt convert tốt hơn browser default vì bạn control được timing
Web App Manifest là file manifest.json khai báo metadata cho PWA:
Lưu ý maskable icon - Android dùng adaptive icons, nếu bạn không có maskable icon thì icon sẽ bị crop xấu trên một số launcher. Dùng Maskable.app - tạo maskable icon để generate maskable icon từ icon thường.
