---
title: "Web app cài được (PWA) có thay thế được app điện thoại không?"
url: https://phatdev.net/vi/blog/pwa-or-native-app
lang: vi
updated: 2026-10-21
alternate:
  en: https://phatdev.net/en/blog/pwa-or-native-app
markdown: https://phatdev.net/vi/blog/pwa-or-native-app.md
---

# Web app cài được (PWA) có thay thế được app điện thoại không?

> PWA làm được gì trên iPhone và Android năm 2026: cài lên màn hình chính, thông báo đẩy, chạy khi mất mạng, giới hạn còn lại và khi nào nên chọn.

Chuyên mục: Ứng dụng di động | Đăng: 2026-10-21 | Cấp độ: Cơ bản | 6 phút đọc

Tags: pwa, service-worker, web-push, ios, android, offline

Một cửa hàng muốn khách đặt hàng bằng điện thoại. Có người khuyên làm app, báo giá cao, chờ vài tháng. Có người khác nói chỉ cần cho website "cài lên màn hình chính" như app là xong. Câu trả lời tuỳ việc bạn cần.

Loại web cài lên màn hình chính có tên chính thức là PWA (Progressive Web App). Bài này nói nó làm được gì và chưa làm được gì trên iPhone và Android năm 2026, để bạn chọn đúng. Mình kiểm nguồn ngày 21/10/2026: MDN, web.dev, blog WebKit, tài liệu Apple và caniuse.

![Một website nhấc biểu tượng lên rồi đáp xuống màn hình chính điện thoại](https://phatdev.net/uploads/blog/pwa-or-native-app/install-1920.webp)

## PWA là gì, nói bằng lời thường

MDN mô tả PWA là ứng dụng xây bằng công nghệ web nhưng cho trải nghiệm giống app của hệ điều hành: cài được lên máy, chạy khi mất mạng, tích hợp với thiết bị. Nó dùng một bộ code duy nhất cho mọi máy.

Hãy nghĩ nó như một cửa hàng online được gắn biển hiệu riêng ngay trên màn hình điện thoại. Khách bấm vào là mở thẳng, không có thanh địa chỉ, nhưng bên trong vẫn là website của bạn. Khi bạn sửa website, mọi khách thấy bản mới, không cần chờ cửa hàng ứng dụng duyệt.

## Cài lên màn hình chính

Trên Android, Chrome cài PWA dưới dạng một app thật nhỏ gọn (gọi là WebAPK) khi máy có dịch vụ Google. Edge và Firefox thì thường chỉ tạo lối tắt có gắn tên trình duyệt.

Trên iPhone, MDN ghi rằng từ iOS 16.4 có thể cài PWA từ menu Chia sẻ của Safari, Chrome, Edge, Firefox và Orion. Nút "cài đặt" tự hiện ngay trong trang (sự kiện beforeinstallprompt) thì iOS không hỗ trợ, nên bạn phải hướng dẫn khách tự bấm Chia sẻ, rồi Thêm vào Màn hình chính. Đây là chỗ cản trở lớn nhất với khách ít rành công nghệ.

Mới hơn: bài WebKit về Safari 26 (đợt beta) cho biết theo mặc định mọi website được thêm vào màn hình chính sẽ mở như một web app, người dùng có thể tắt bằng công tắc "Mở như web app". Vì mình lấy từ thông báo beta, bạn nên thử trên máy thật trước khi hứa với khách.

Ở châu Âu, Apple từng định bỏ tính năng này khi tuân thủ luật DMA, rồi cho biết vẫn giữ nguyên, và tính năng trở lại với iOS 17.4 vào tháng 3/2024.

## Chạy khi mất mạng

Phần chạy không mạng dựa vào một đoạn code nền gọi là service worker. Nó giống một nhân viên đứng cổng: khi khách mở app, nó kiểm xem có mạng không, nếu không thì lấy bản đã lưu sẵn trong máy ra đưa cho khách. MDN nêu hai kho chứa chính: Cache cho các file giao diện, và IndexedDB cho dữ liệu có cấu trúc.

![Điện thoại có kho lưu tạm, đám mây gạch chéo nhưng màn hình vẫn hiện nội dung, chuông thông báo bên cạnh](https://phatdev.net/uploads/blog/pwa-or-native-app/offline-1920.webp)

Điều này hợp với danh mục sản phẩm xem lại, phiếu đã mở, danh sách việc cần làm. Không hợp với thứ cần dữ liệu mới theo từng giây như tồn kho hay thanh toán. Với chúng, app hay web đều phải có mạng.

Một giới hạn cần biết: tính năng Background Sync (hẹn gửi dữ liệu khi có mạng lại, ngay cả khi đã đóng app) chạy trên Chrome nhưng theo caniuse thì Safari trên iOS chưa hỗ trợ ở bất kỳ phiên bản nào tới 27.2, Firefox cũng chưa. Vì thế nếu bạn cần "đồng bộ ngầm khi đóng app", PWA trên iPhone chưa đáp ứng được.

## Thông báo đẩy

Thông báo đẩy (push) là tin nhắn hiện lên màn hình khoá dù khách không mở app. Blog WebKit ghi: từ iOS và iPadOS 16.4, web app đã thêm vào màn hình chính có thể xin phép gửi thông báo. Có ba điều kiện: phải cài lên màn hình chính trước, lời xin phép phải đến từ một thao tác của khách như bấm nút "Bật thông báo", và dùng các chuẩn Push API, Notifications API, Service Worker. Bạn không cần tài khoản Apple Developer.

Nghĩa là trên iPhone, khách chưa cài PWA thì sẽ không nhận được thông báo. Trên Android thì dễ hơn. Nếu thông báo là trái tim của kinh doanh (nhắc lịch, báo đơn hàng), hãy tính tỷ lệ khách chịu làm bước cài.

## Khi nào nên chọn PWA

Hợp khi bạn là cửa hàng hay dịch vụ cần có mặt trên điện thoại nhanh, nội dung chủ yếu là xem, đặt hàng, tra cứu, form; khi bạn đã có website tốt và muốn tận dụng; khi ngân sách và thời gian hạn chế; khi tránh phụ thuộc cửa hàng ứng dụng. Nếu chưa có website tốt, nên bắt đầu từ đó, xem bài [Làm web nên chọn WordPress hay code riêng?](https://phatdev.net/vi/blog/wordpress-or-custom-code) và [Web chậm làm mất khách thế nào, và cách tự kiểm tốc độ trong 5 phút](https://phatdev.net/vi/blog/page-speed-and-sales).

![Biển chỉ đường chia hai hướng: web app cài được và app trong cửa hàng](https://phatdev.net/uploads/blog/pwa-or-native-app/choose-1920.webp)

## Khi nào nên làm app thật

Nên làm app khi tính năng dựa nhiều vào phần cứng và hệ điều hành (camera nâng cao, Bluetooth, chạy nền lâu, cảm biến), khi cần có mặt trong cửa hàng ứng dụng để khách tìm thấy, khi cần thanh toán trong ứng dụng, hoặc khi khách mong đợi một app đúng nghĩa. Cách chọn công nghệ làm app mình viết ở [Làm app điện thoại: nên chọn Swift/Kotlin, Flutter hay React Native?](https://phatdev.net/vi/blog/app-native-or-cross-platform), còn thủ tục lên cửa hàng ở [Đưa app lên App Store và Google Play: danh sách việc cần chuẩn bị (2026)](https://phatdev.net/vi/blog/app-store-google-play-checklist).

Có một cạm bẫy: đừng bọc nguyên website vào một cái vỏ rồi nộp lên App Store. Mục 4.2 trong App Review Guidelines của Apple yêu cầu app phải có nhiều hơn một website được đóng gói lại.

## Cho bạn nào viết code

Một PWA tối thiểu cần ba thứ: trang chạy qua HTTPS (hoặc localhost khi thử), một file manifest, và một service worker nếu muốn chạy khi mất mạng. Theo MDN, service worker không bắt buộc để cài được, nhưng các trình duyệt nền Chromium yêu cầu manifest có tên, biểu tượng 192 và 512 px, start_url, display, và `prefer_related_applications` không bật.

Manifest mình dùng thử:

```json
{
  "name": "Cua hang demo",
  "short_name": "Demo",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#0e7490",
  "icons": [
    { "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
    { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" }
  ]
}
```

Service worker đơn giản: lưu khung trang lúc cài, ưu tiên mạng, mất mạng thì lấy từ bản lưu.

```js
const CACHE = "shell-v1";
const SHELL = ["/", "/manifest.webmanifest"];

self.addEventListener("install", (e) => {
  e.waitUntil(caches.open(CACHE).then((c) => c.addAll(SHELL)));
  self.skipWaiting();
});

self.addEventListener("fetch", (e) => {
  if (e.request.method !== "GET") return;
  e.respondWith(fetch(e.request).catch(() => caches.match(e.request)));
});
```

Mình chạy thử bằng Chromium: service worker đăng ký và kiểm soát trang, hai file được lưu, rồi tắt mạng và tải lại thì trang vẫn hiện đúng. Mình chưa thử trên iPhone thật.

## Lỗi hay gặp

Chuyện dễ xảy ra nhất là sửa website xong mà khách vẫn thấy bản cũ, vì service worker đã lưu bản cũ. Hãy đổi tên bộ nhớ (ví dụ shell-v2) mỗi lần phát hành và xoá bản cũ. Một lỗi khác là lưu cả trang giỏ hàng hay trang thanh toán, khiến khách thấy dữ liệu cũ. Chỉ lưu những gì an toàn khi xem lại.

## Làm gì tiếp theo

Viết ra ba tính năng khách cần nhất, rồi đối chiếu với các giới hạn ở trên, đặc biệt thông báo đẩy và chạy nền trên iPhone. Nếu cả ba đều làm được bằng web, PWA là bước đầu rẻ và nhanh. Nếu không, bạn đã biết chính xác vì sao cần app thật.

## Nguồn tham khảo

- [MDN: Progressive web apps](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps)
- [MDN: Making PWAs installable](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Making_PWAs_installable)
- [web.dev: Learn PWA](https://web.dev/learn/pwa/)
- [WebKit: Web Push for Web Apps on iOS and iPadOS](https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/)
- [WebKit: News from WWDC25, Safari 26 beta](https://webkit.org/blog/16993/news-from-wwdc25-web-technology-coming-this-fall-in-safari-26-beta/)
- [Apple: Update on apps distributed in the European Union](https://developer.apple.com/support/dma-and-apps-in-the-eu)
- [caniuse: Background Sync API](https://caniuse.com/background-sync)
- [App Review Guidelines, 4.2](https://developer.apple.com/app-store/review/guidelines/)

## Bài liên quan

- [Làm app điện thoại: nên chọn Swift/Kotlin, Flutter hay React Native?](https://phatdev.net/vi/blog/app-native-or-cross-platform.md)
- [Đưa app lên App Store và Google Play: danh sách việc cần chuẩn bị (2026)](https://phatdev.net/vi/blog/app-store-google-play-checklist.md)
- [Làm web nên chọn WordPress hay code riêng?](https://phatdev.net/vi/blog/wordpress-or-custom-code.md)
