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

如何为Angular CLI生成的Service Worker添加自定义代码

扩展Angular CLI生成的Service Worker功能

我之前也碰到过这个需求——Angular官方的Service Worker(也就是ngsw-worker.js)确实没提供直接修改它的官方文档,但咱们有办法扩展它的功能,比如添加推送通知、消息处理这些。下面是两种可行的方案,你可以根据需求选:

方案一:用“代理Worker”包裹ngsw-worker.js(适合底层自定义)

这种方法是创建一个自定义的Service Worker,导入Angular原生的ngsw-worker.js,然后在上面叠加自己的逻辑,完全可控。

步骤1:创建自定义Worker文件

在项目src目录下新建custom-sw.js,内容如下:

// 先导入Angular原生的Service Worker,确保它的缓存等逻辑先执行
importScripts('./ngsw-worker.js');

// 自定义推送通知监听
self.addEventListener('push', (event) => {
  const payload = event.data?.json() || {};
  const notificationOptions = {
    title: payload.title || '新通知',
    body: payload.body || '你有一条未读消息',
    icon: '/assets/icons/icon-192x192.png', // 换成你项目里的图标路径
    data: payload.data || {}
  };

  // 显示通知
  event.waitUntil(
    self.registration.showNotification(notificationOptions.title, notificationOptions)
  );
});

// 处理通知点击事件
self.addEventListener('notificationclick', (event) => {
  event.notification.close();
  // 点击后打开指定页面,这里可以根据payload里的url动态调整
  event.waitUntil(
    clients.openWindow(event.notification.data.url || '/')
  );
});

// 自定义消息监听(和页面通信)
self.addEventListener('message', (event) => {
  console.log('收到来自页面的消息:', event.data);
  // 给页面回复消息
  if (event.source) {
    event.source.postMessage('Service Worker已收到你的消息~');
  }
});

步骤2:修改Angular项目配置

打开angular.json,找到你的项目配置,调整Service Worker相关设置:

"projects": {
  "你的项目名称": {
    "architect": {
      "build": {
        "options": {
          // 关闭Angular自动注册原生Service Worker的功能
          "serviceWorker": false,
          // 保留ngsw配置文件,这样Angular的缓存策略依然生效
          "ngswConfigPath": "src/ngsw-config.json"
        }
      }
    }
  }
}

步骤3:手动注册自定义Worker

修改src/main.ts,替换原来的Angular Service Worker注册代码,改成注册我们的自定义Worker:

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();

  // 注册自定义Service Worker
  if ('serviceWorker' in navigator) {
    window.addEventListener('load', async () => {
      try {
        const registration = await navigator.serviceWorker.register('/custom-sw.js');
        console.log('自定义Service Worker注册成功:', registration);

        // 这里可以添加推送订阅逻辑
        const vapidPublicKey = '你的VAPID公钥'; // 换成你自己生成的公钥
        const subscription = await registration.pushManager.subscribe({
          userVisibleOnly: true,
          applicationServerKey: vapidPublicKey
        });
        console.log('推送订阅成功:', subscription);
        // 把订阅信息发送给你的后端服务器,方便后续推送消息
      } catch (err) {
        console.error('Service Worker注册失败:', err);
      }
    });
  }
}

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.error(err));

步骤4:构建测试

运行ng build --prod打包生产版本,然后用HTTP服务器(比如http-server dist/你的项目名称)启动,测试自定义功能即可。

方案二:用Angular官方的SwPush服务(适合快速实现推送)

如果你只是需要推送通知功能,其实Angular已经封装了SwPush服务,不用直接碰Service Worker文件,更贴合Angular生态:

1. 在组件中使用SwPush

比如在app.component.ts里:

import { Component, OnInit } from '@angular/core';
import { SwPush } from '@angular/service-worker';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  private readonly VAPID_PUBLIC_KEY = '你的VAPID公钥';

  constructor(private swPush: SwPush) {}

  ngOnInit(): void {
    // 检查Service Worker是否启用
    if (this.swPush.isEnabled) {
      // 请求推送订阅
      this.swPush.requestSubscription({
        serverPublicKey: this.VAPID_PUBLIC_KEY
      }).then(subscription => {
        // 将订阅信息发送到后端
        console.log('推送订阅成功,订阅信息:', subscription);
      }).catch(err => {
        console.error('推送订阅失败:', err);
      });

      // 监听推送消息
      this.swPush.messages.subscribe(message => {
        console.log('收到推送消息:', message);
        // 这里可以自定义显示通知的逻辑
        alert(`新消息:${message.body}`);
      });
    }
  }
}

2. 注意事项

  • 这种方式需要你保持Angular的Service Worker配置(也就是angular.json里serviceWorker: true)
  • VAPID密钥需要自己生成,可以用web-push工具生成,后端也要配置对应的私钥来发送推送请求

关键提醒

  • 不管用哪种方案,VAPID密钥是推送功能的必要条件,别忘生成和配置
  • 自定义Worker方案里,一定要把importScripts('./ngsw-worker.js')放在最前面,确保Angular原生的Service Worker逻辑先执行
  • 测试Service Worker必须用HTTPS环境(localhost除外),不然浏览器会限制功能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:46:13