You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular v15 PWA推送通知仅PC可用,求全设备无Node实现方案

全设备推送通知实现方案(Angular 15 PWA + .NET 7,无Node依赖)

核心问题先排查

先解决现有移动端失效的常见诱因:

  • 确认移动端浏览器支持Push API与PWA:Chrome、Firefox移动端原生支持,Safari需升级至16.4及以上版本
  • 强制HTTPS环境:移动端仅信任HTTPS站点,本地开发可通过ngrok转发本地服务到公网HTTPS地址
  • 检查Service Worker状态:移动端需确保SW完成注册并激活,可在浏览器开发者工具Application > Service Workers面板查看

完整实现步骤

1. 清理非PWA依赖

卸载仅支持PC的ng-push-notification包,改用Angular PWA原生能力:

npm uninstall ng-push-notification

2. 配置Angular PWA基础

确保@angular/service-worker已正确集成:

  • 在angular.json中确认projects.[你的项目名].architect.build.options.serviceWorker设为true
  • 在app.module.ts注册Service Worker:
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';

@NgModule({
  imports: [
    // 其他模块
    ServiceWorkerModule.register('ngsw-worker.js', {
      enabled: environment.production,
      registrationStrategy: 'registerWhenStable:30000'
    })
  ]
})
export class AppModule { }

3. 客户端推送订阅逻辑(兼容移动端)

在Angular组件或服务中实现订阅流程:

import { SwPush } from '@angular/service-worker';
import { HttpClient } from '@angular/common/http';

constructor(private swPush: SwPush, private http: HttpClient) {}

async subscribeToPush() {
  if (!this.swPush.isEnabled) {
    alert('当前环境不支持推送通知,请确保浏览器开启PWA支持');
    return;
  }

  // 请求通知权限
  const permission = await Notification.requestPermission();
  if (permission !== 'granted') {
    alert('需开启通知权限才能接收推送');
    return;
  }

  // 从.NET后端获取VAPID公钥
  const vapidPublicKey = await this.http.get<string>('/api/push/vapidpublickey').toPromise();
  const convertedKey = this.urlBase64ToUint8Array(vapidPublicKey);

  // 发起推送订阅
  const subscription = await this.swPush.requestSubscription({
    serverPublicKey: convertedKey
  });

  // 将订阅信息提交到后端存储
  await this.http.post('/api/push/subscribe', subscription).toPromise();
}

// 转换VAPID公钥格式的辅助函数
private urlBase64ToUint8Array(base64String: string): Uint8Array {
  const padding = '='.repeat((4 - base64String.length % 4) % 4);
  const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
  const rawData = window.atob(base64);
  return Uint8Array.from([...rawData].map(char => char.charCodeAt(0)));
}

4. .NET 7后端实现(无Node依赖)

集成WebPush库

通过NuGet安装推送依赖:

Install-Package WebPush

生成VAPID密钥对(仅需生成一次,存储到appsettings.json):

using WebPush;

var vapidKeys = VapidHelper.GenerateVapidKeys();
// 示例:将公钥和私钥写入appsettings.json
// "VapidPublicKey": "生成的公钥",
// "VapidPrivateKey": "生成的私钥"

订阅存储接口

创建API接收客户端订阅信息并存储(可使用SQL Server、Redis等):

[ApiController]
[Route("api/push")]
public class PushController : ControllerBase
{
    private readonly IPushSubscriptionRepository _subscriptionRepo;

    public PushController(IPushSubscriptionRepository subscriptionRepo)
    {
        _subscriptionRepo = subscriptionRepo;
    }

    [HttpPost("subscribe")]
    public async Task<IActionResult> SaveSubscription([FromBody] PushSubscription subscription)
    {
        await _subscriptionRepo.UpsertSubscription(subscription);
        return Ok();
    }
}

推送发送逻辑

编写发送推送的方法,处理订阅过期等异常:

public async Task SendPushNotification(PushSubscription subscription, string title, string content)
{
    var vapidDetails = new VapidDetails(
        "mailto:your-contact@example.com",
        Configuration["VapidPublicKey"],
        Configuration["VapidPrivateKey"]
    );

    var webPushClient = new WebPushClient();
    var payload = JsonSerializer.Serialize(new { title, content });
    var payloadBytes = Encoding.UTF8.GetBytes(payload);

    try
    {
        await webPushClient.SendNotificationAsync(subscription, payloadBytes, vapidDetails);
    }
    catch (WebPushException ex)
    {
        // 订阅过期时从存储中移除
        if (ex.StatusCode == HttpStatusCode.Gone)
        {
            await _subscriptionRepo.DeleteSubscription(subscription.Endpoint);
        }
    }
}

5. 移动端适配细节

  • 完善Web App Manifest:确保manifest.webmanifest包含name、short_name、start_url、display: standalone,让用户可将PWA添加到移动端主屏幕
  • 配置通知行为:在ngsw-config.json中设置通知图标、点击逻辑:
{
  "notificationOptions": {
    "icon": "assets/icons/icon-192x192.png",
    "badge": "assets/icons/badge-72x72.png"
  },
  "push": {
    "showNotifications": true,
    "backgroundNotification": "cache-and-update"
  }
}
  • iOS Safari适配:iOS 16.4+版本需用户手动将PWA添加到主屏幕,才能接收推送通知

验证方案

  • 本地测试:用ngrok转发本地HTTPS服务到公网,在移动端访问转发地址完成订阅测试
  • 生产验证:部署到HTTPS服务器,测试移动端添加主屏幕后的推送接收情况

内容的提问来源于stack exchange,提问作者RowdyCodeU

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 05:53:19