3.7PWA (Progressive Web Apps) 支持 3.7 PWA (Progressive Web Apps) 支持 Progressive Web Apps (PWA) 是一种使用现代 Web 功能来提供类似原生应用体验的 Web 应用。Angular 提供了强大的工具和支持,使创建 PWA 变得更加容易。 3.7.1 PWA 的优势 可靠性 (Reliable): 即使在网络状况不佳或离线状态下,也能立即加载并提供基本功能。 快速 (Fast): 对用户交互做出快速响应,提供流畅的用户体验。 吸引力 (Engaging): 可以像原生应用一样安装到设备主屏幕,并通过推送通知等功能重新吸引用户。 3.7.
Progressive Web Apps (PWA) 是一种使用现代 Web 功能来提供类似原生应用体验的 Web 应用。Angular 提供了强大的工具和支持,使创建 PWA 变得更加容易。
可靠性 (Reliable): 即使在网络状况不佳或离线状态下,也能立即加载并提供基本功能。
快速 (Fast): 对用户交互做出快速响应,提供流畅的用户体验。
吸引力 (Engaging): 可以像原生应用一样安装到设备主屏幕,并通过推送通知等功能重新吸引用户。
Service Worker: 一个在浏览器后台运行的脚本,用于缓存应用资源、处理网络请求和推送通知。
Web App Manifest: 一个 JSON 文件,描述了应用的名称、图标、启动画面等信息,用于安装到主屏幕。
HTTPS: PWA 必须通过 HTTPS 提供服务,以确保安全性和数据完整性。
Angular CLI 提供了简化 PWA 创建过程的命令。
创建 Angular 项目 (如果还没有):
ng new my-pwa-app cd my-pwa-app
添加 PWA 支持:
ng add @angular/pwa
这个命令会自动执行以下操作:
安装 @angular/pwa 包。
导入 ServiceWorkerModule 到 app.module.ts。
创建 manifest.webmanifest 文件。
创建 ngsw-config.json 文件 (用于配置 Service Worker)。
注册 Service Worker。
添加必要的图标。
更新 angular.json 文件。
构建 PWA:
ng build --prod
--prod 标志用于生成优化的生产版本,包括代码压缩、tree shaking 等。
测试 PWA:
可以使用 http-server 或类似的工具来提供构建后的应用。
npm install -g http-server http-server dist/my-pwa-app -p 8080
然后,在浏览器中访问 http://localhost:8080。
manifest.webmanifest 文件详解manifest.webmanifest 文件描述了 PWA 的元数据。以下是一个示例:
{ "name": "My PWA App", "short_name": "My PWA", "theme_color": "#1976d2", "background_color": "#fafafa", "display": "standalone", "scope": "/", "start_url": "/", "icons": [ { "src": "assets/icons/icon-72x72.png", "sizes": "72x72", "type": "image/png" }, { "src": "assets/icons/icon-96x96.png", "sizes": "96x96", "type": "image/png" }, { "src": "assets/icons/icon-128x128.png", "sizes": "128x128", "type": "image/png" }, { "src": "assets/icons/icon-144x144.png", "sizes": "144x144", "type": "image/png" }, { "src": "assets/icons/icon-152x152.png", "sizes": "152x152", "type": "image/png" }, { "src": "assets/icons/icon-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "assets/icons/icon-384x384.png", "sizes": "384x384", "type": "image/png" }, { "src": "assets/icons/icon-512x512.png", "sizes": "512x512", "type": "image/png" } ] }
name: 应用的完整名称。
short_name: 应用的简短名称,用于主屏幕。
theme_color: 应用的主题颜色。
background_color: 应用的背景颜色。
display: 应用的显示模式 (standalone, fullscreen, minimal-ui, browser)。 standalone 模式会隐藏浏览器的地址栏。
scope: 定义了 PWA 的导航范围。
start_url: 应用启动时加载的 URL。
icons: 应用使用的图标列表,用于不同的设备和分辨率。
ngsw-config.json 文件详解ngsw-config.json 文件配置了 Service Worker 的缓存策略。以下是一个示例:
{ "$schema": "./node_modules/@angular/service-worker/config/schema.json", "index": "/index.html", "assetGroups": [ { "name": "app", "installMode": "prefetch", "resources": { "files": [ "/favicon.ico", "/index.html", "/manifest.webmanifest", "/assets/icons/*.png" ], "versionedFiles": [ "/*.bundle.*.js", "/*.chunk.*.js", "/*.map", "/styles.*.css" ] } }, { "name": "assets", "installMode": "lazy", "updateMode": "prefetch", "resources": { "files": [ "/assets/**" ], "versionedFiles": [] } } ], "dataGroups": [ { "name": "api", "urls": [ "/api/**" ], "cacheConfig": { "strategy": "performance", "maxSize": 100, "maxAge": "1h", "timeout": "5s" } } ] }
index: 应用的入口文件。
assetGroups: 定义了一组要缓存的资源。
name: 组的名称。
installMode: prefetch (在 Service Worker 安装时缓存) 或 lazy (在需要时缓存)。
updateMode: prefetch (在后台更新缓存) 或 lazy (仅在需要时更新缓存)。
resources: 要缓存的文件列表。
files: 要精确匹配的文件。
versionedFiles: 包含版本哈希的文件 (例如,由 Angular CLI 生成的 bundle 文件)。
dataGroups: 定义了 API 请求的缓存策略。
name: 组的名称。
urls: 要缓存的 URL 模式。
cacheConfig: 缓存配置。
strategy: performance (优先返回缓存,然后更新) 或 freshness (优先从网络获取,然后缓存)。
maxSize: 缓存的最大条目数。
maxAge: 缓存条目的最大生存时间。
timeout: 网络请求的超时时间。
缓存策略选择:
performance: 适用于不经常更新的数据,例如静态资源。
freshness: 适用于需要最新数据的情况,例如新闻文章。
Service Worker 的生命周期包括以下阶段:
Install: Service Worker 安装时触发。可以在此阶段缓存静态资源。
Activate: Service Worker 激活时触发。可以在此阶段清理旧的缓存。
Fetch: 拦截网络请求时触发。可以从缓存返回响应或发起新的网络请求。
Message: 接收到来自客户端的消息时触发。
SwUpdate 服务更新 PWASwUpdate 服务允许你检查和安装 PWA 的更新。
导入 SwUpdate 服务:
import { SwUpdate } from '@angular/service-worker'; import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { title = 'my-pwa-app'; constructor(private swUpdate: SwUpdate) {} ngOnInit() { if (this.swUpdate.isEnabled) { this.swUpdate.available.subscribe(() => { if (confirm('New version available. Load New Version?')) { window.location.reload(); } }); } } }
检查更新:
在 ngOnInit 方法中,检查 SwUpdate 是否启用,并订阅 available 事件。当有新版本可用时,提示用户重新加载页面。
要实现推送通知,需要使用 Firebase Cloud Messaging (FCM) 或类似的推送服务。
配置 Firebase:
在 Firebase 控制台中创建一个项目。
添加一个 Web 应用。
获取 Firebase 配置。
安装 Firebase SDK:
npm install firebase @angular/fire
初始化 Firebase:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { AngularFireModule } from '@angular/fire/compat'; import { AngularFireMessagingModule } from '@angular/fire/compat/messaging'; const firebaseConfig = { apiKey: "YOUR_API_KEY", authDomain: "YOUR_AUTH_DOMAIN", projectId: "YOUR_PROJECT_ID", storageBucket: "YOUR_STORAGE_BUCKET", messagingSenderId: "YOUR_MESSAGING_SENDER_ID", appId: "YOUR_APP_ID", measurementId: "YOUR_MEASUREMENT_ID" }; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule, AngularFireModule.initializeApp(firebaseConfig), AngularFireMessagingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
获取推送通知权限:
import { Component, OnInit } from '@angular/core'; import { AngularFireMessaging } from '@angular/fire/compat/messaging'; import { SwUpdate } from '@angular/service-worker'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { title = 'my-pwa-app'; constructor(private swUpdate: SwUpdate, private afMessaging: AngularFireMessaging) {} ngOnInit() { if (this.swUpdate.isEnabled) { this.swUpdate.available.subscribe(() => { if (confirm('New version available. Load New Version?')) { window.location.reload(); } }); } this.requestPermission(); } requestPermission() { this.afMessaging.requestToken.subscribe( (token) => { console.log('Permission granted! Save to the server!', token); }, (error) => { console.error('Failed to request permission:', error); } ); } }
处理推送通知:
Firebase 会自动处理推送通知的显示。你可以在 firebase-messaging-sw.js 文件中自定义通知的处理方式。
使用 HTTPS: 确保应用通过 HTTPS 提供服务。
优化性能: 使用代码压缩、图片优化和缓存来提高应用的加载速度。
响应式设计: 确保应用在不同的设备上都能正常显示。
提供离线体验: 缓存关键资源,以便在离线状态下提供基本功能。
使用 Lighthouse 进行评估: 使用 Lighthouse 工具来评估 PWA 的质量,并根据建议进行改进。
Angular 提供了强大的工具和支持,使创建 PWA 变得更加容易。通过使用 Angular CLI、Service Worker、Web App Manifest 和其他 PWA 功能,你可以创建具有类似原生应用体验的 Web 应用。记住遵循最佳实践,以确保你的 PWA 具有高性能、可靠性和吸引力。