ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Angular Service Worker 扩展实战:编写自定义 Service Worker 脚本并接管注册

Angular Service Worker 扩展实战:编写自定义 Service Worker 脚本并接管注册 Angular Service Worker 扩展实战编写自定义 Service Worker 脚本并接管注册【免费下载链接】angularDeliver web apps with confidence 项目地址: https://gitcode.com/GitHub_Trending/an/angularAngular 自带的 Service WorkerNGSW定位是一个功能收敛的基础缓存工具官方明确不再接受新功能除安全修复而推送通知、后台同步等能力需要通过自定义脚本扩展。本文以 自定义 Service Worker 脚本指南 为主线完整讲解“编写自定义 SW 脚本 → 接入构建产物 → 修改provideServiceWorker注册入口”的三步流程并结合angular/service-worker的源码provider.ts验证注册链路与各配置项的真实行为帮助你在不破坏 Angular 内建缓存与更新机制的前提下为应用加入通知点击、后台同步等原生 Service Worker 事件处理。为什么需要自定义 Service Worker 脚本Angular 的 Service Worker 负责应用级的缓存、离线加载与后台版本更新它在构建时从ngsw-config.json生成ngsw.json清单运行时由 worker/main.ts 中的Driver驱动整个缓存与更新流程。但官方文档在 overview 中明确提示Angular Service Worker is a basic caching utility for simple offline support with a limited featureset. We will not be accepting any new features other than security fixes. For more advanced caching and offline capabilities, we recommend exploring native browser APIs directly.也就是说内建 Worker 不会替你处理push、sync、notificationclick这类事件。解法是新建一个自定义 Service Worker 脚本在其中先导入并复用 Angular 的ngsw-worker.js再追加自己的事件处理器。这样既保留了内建的全部缓存/更新能力又获得了原生的扩展点。从源码看注册入口与脚本内容完全解耦provider.ts 中的provideServiceWorker(script, options)只是把script字符串存入SCRIPT注入令牌最终传给navigator.serviceWorker.register(script, ...)。因此“换掉注册的脚本文件名”本身就是官方支持的扩展方式这也是该指南中see Custom service worker script注释指向本文的原因。第一步创建继承 Angular Service Worker 的自定义脚本在项目的src目录指南示例中为app/src/custom-sw.js创建自定义 Service Worker 文件custom-sw.js完整代码如下与指南一致// Import the Angular service worker importScripts(./ngsw-worker.js); (function () { use strict; // Add custom notification click handler self.addEventListener(notificationclick, (event) { console.log(Custom notification click handler); console.log(Notification details:, event.notification); // Handle notification click - open URL if provided if (clients.openWindow event.notification.data.url) { event.waitUntil(clients.openWindow(event.notification.data.url)); console.log(Opening URL:, event.notification.data.url); } }); // Add custom background sync handler self.addEventListener(sync, (event) { console.log(Custom background sync handler); if (event.tag background-sync) { event.waitUntil(doBackgroundSync()); } }); function doBackgroundSync() { // Implement your background sync logic here return fetch(https://example.com/api/sync) .then((response) response.json()) .then((data) console.log(Background sync completed:, data)) .catch((error) console.error(Background sync failed:, error)); } })();这段脚本有三个关键设计点首行importScripts(./ngsw-worker.js)不可省略、不可后置。ngsw-worker.js是构建产物见 packages/service-worker/BUILD.bazel 中outs [ngsw-worker.js]它会执行内建 Worker 的Driver初始化读取ngsw.json清单、接管fetch拦截、管理 IndexedDB 缓存数据库。你的自定义脚本必须先把它跑起来才能在同一个全局self上叠加事件监听。IIFE 包裹自定义逻辑use strict 立即执行函数避免污染 Service Worker 全局作用域。注意importScripts是 classic worker 的 API——这与provideServiceWorker的type选项默认为classic正好匹配见下文“源码解析”。异步操作一律挂在event.waitUntil()上clients.openWindow(...)与后台同步的fetch都通过它注册确保事件处理器返回后浏览器不会提前终止 Service Worker。notificationclick中的clients.openWindow存在性检查则是兼容性兜底部分移动端环境不支持从通知直接打开窗口。第二步把自定义脚本纳入构建产物自定义脚本必须和ngsw-worker.js一起出现在部署目录的根部因为脚本内用的是相对路径./ngsw-worker.js。指南的做法是在angular.json的build目标中将custom-sw.js作为一条 asset 复制到输出目录{ projects: { your-app: { architect: { build: { options: { assets: [ { glob: **/*, input: public }, app/src/custom-sw.js ] } } } } } }说明数组第一项{ glob: **/*, input: public }是 CLI 新版本默认的静态资源目录约定最后一项app/src/custom-sw.js则是把自定义 Worker 文件原样拷贝到dist/project/browser/下与ngsw-worker.js同级。构建后在部署目录中应能同时看到custom-sw.js、ngsw-worker.js和ngsw.json。三者缺一不可custom-sw.js是入口ngsw-worker.js是内建实现ngsw.json是内建 Worker 启动时读取的资源清单详见 配置文档。与 ngsw-config.json 的 glob 规则、resourcesOutputPath等细节无关——自定义脚本走的是assets拷贝通道直接成为版本化产物的一部分。第三步将注册入口指向自定义脚本最后一步是让 Angular 应用注册的不再是ngsw-worker.js而是custom-sw.js。在应用根 provider 中修改provideServiceWorker的第一个参数指南原文import {ApplicationConfig, isDevMode} from angular/core; import {provideServiceWorker} from angular/service-worker; export const appConfig: ApplicationConfig { providers: [ provideServiceWorker(custom-sw.js, { enabled: !isDevMode(), registrationStrategy: registerWhenStable:30000, }), ], };各选项含义与 getting-started 中的 Service worker configuration 一节一致并在源码中得到验证选项取值作用enabledboolean默认true为false时不注册 WorkerSwPush/SwUpdate也不会尝试与其通信。示例中用!isDevMode()让开发模式ng serve默认走 dev 配置完全绕过 Service Worker避免开发期缓存干扰。registrationStrategy字符串或 Observable 工厂默认registerWhenStable:30000应用进入稳定态无挂起的微/宏任务时注册最多等 30 秒也支持registerImmediately、registerWithDelay:ms以及返回Observable的工厂函数。typeclassic默认或module决定navigator.serviceWorker.register()的脚本类型。自定义脚本使用importScripts必须保持classic若改为moduleimportScripts将不可用。scope字符串默认脚本所在目录控制 Worker 可拦截的 URL 范围。updateViaCacheimports/all/none控制浏览器更新 Worker 及其导入脚本时是否查询 HTTP 缓存。源码解析注册链路与策略的落地行为结合 provider.ts 可以看清上述配置如何生效脚本名如何被使用provideServiceWorker返回的 provider 集合中包含{provide: SCRIPT, useValue: script}L247。应用初始化器ngswAppInitializer通过inject(SCRIPT)取出该字符串并在 L105-L110 调用navigator.serviceWorker.register(script, {scope, updateViaCache, type})。因此传入custom-sw.js后浏览器实际拉取的第一个脚本就是你的自定义文件它再链式加载ngsw-worker.js——这正是“扩展”而非“替换”的实现路径。策略解析逻辑字符串策略按:切分L73-L92registerWhenStable分支用Promise.race([appRef.whenStable(), delayWithTimeout(args[0])])实现“稳定即注册、超时兜底”未知策略抛出NG05600运行时错误。函数策略则等待 Observable 首次发射。这些行为在 provider_spec.ts 中有系统性单测覆盖包括默认 30 秒兜底tick(30000)后必须已调用register、registerWhenStable:0的异步即注册、以及“应用已销毁则不再注册”等场景。失败兜底注册失败不会导致未捕获 Promise 拒绝源码在.catch中记录NG05604错误L111-L119测试 provider_spec.ts#L136-L144 验证了这一点。对自定义脚本尤其重要custom-sw.js一旦 404 或语法错误你只会看到控制台日志而不会知道推送/同步链路已经断了。type: module的边界SwRegistrationOptions的文档注释L169-L177说明module允许import/export语法而本指南的自定义脚本方案依赖importScripts二者互斥保持默认classic即可。内建 Worker 的启动方式ngsw-worker.js的入口是 worker/main.ts 中的三行代码——构造Adapter、CacheDatabase并new Driver(scope, adapter, new CacheDatabase(adapter))。Driver 在构造时就开始监听install/activate/fetch等事件。你的自定义脚本在其importScripts之后注册的notificationclick、sync监听器与 Driver 的事件处理器共存于同一个全局作用域互不覆盖——这解释了为什么该扩展模式不会破坏内建缓存逻辑。最佳实践与常见用途指南给出的五条实践建议逐条对应到上面的实现细节始终先用importScripts(./ngsw-worker.js)导入 Angular Service Worker确保缓存与更新能力完整保留用 IIFE 包裹自定义代码避免污染全局作用域内建 Worker 的 Driver 状态全部挂在闭包内你的顶层变量不应与其命名冲突;异步操作使用event.waitUntil()防止 Service Worker 在异步任务完成前被浏览器终止开发与生产环境都要测试生产走 HTTPS 且注册内建 Worker开发环境若设置了enabled: !isDevMode()需要临时改为true或用ng serve --configurationproduction验证自定义脚本本身优雅处理错误自定义代码中的异常若处理不当可能拖垮整个 Worker 上下文进而影响内建缓存功能。指南示例中doBackgroundSync()自带.catch就是这一点的体现。自定义 Service Worker 的典型用途指南原文列举推送通知接收push消息并展示系统通知可继续参考 Push notifications 指南后台同步在网络恢复后通过sync事件补传数据即上文doBackgroundSync()的场景自定义导航处理特殊路由或离线页面的跳转逻辑。验证清单完成三步改造后可按以下顺序验证ng build后确认dist/project/browser/下同时存在custom-sw.js与ngsw-worker.js用支持 Service Worker 的环境访问应用HTTPS 或localhost参考 getting-started在 DevTools 的 Application 面板确认注册的 Worker 脚本是custom-sw.js查看 Network 面板确认静态资源请求来源标记为(ServiceWorker)说明内建缓存链路经由自定义脚本正常工作触发一次通知点击或同步事件确认Custom notification click handler等日志出现且event.waitUntil中的异步操作完整执行。相关文档Service Worker 概述、ngsw-config.json 配置、与 Service Worker 通信、推送通知、DevOps 指南。【免费下载链接】angularDeliver web apps with confidence 项目地址: https://gitcode.com/GitHub_Trending/an/angular创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表