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

Angular 17中Service Worker离线模式失效问题求助

解决Angular 17 PWA离线数据未缓存加载问题

问题概述

已通过@angular/pwa命令安装并成功注册Service Worker,但进入离线模式后页面显示无网络,接口数据未被缓存加载,需针对Angular 17版本提供解决方案。

现有配置代码

App.Module.ts

import { NgModule, isDevMode } from '@angular/core';
import { BrowserModule, provideClientHydration } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ServiceWorkerModule } from '@angular/service-worker';
import { PostComponent } from './components/post/post.component';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
    PostComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    ServiceWorkerModule.register('ngsw-worker.js', {
      enabled: isDevMode(),
      // Register the ServiceWorker as soon as the application is stable
      // or after 30 seconds (whichever comes first).
      registrationStrategy: 'registerWhenStable:30000',
      scope: '/'
    })
  ],
  providers: [
    provideClientHydration()
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

index.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>PwaDemo</title>
  <base href="./">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link href="https://fonts.googleapis.com/css2?family=Single+Day&display=swap" rel="stylesheet">
  <link rel="manifest" href="manifest.webmanifest">
  <meta name="theme-color" content="#1976d2">
</head>
<body>
  <app-root></app-root>
  <noscript>Please enable JavaScript to continue using this application.</noscript>
</body>
</html>

ngsw-config.json

{
  "$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",
          "/*.css",
          "/*.js"
        ],
        "urls": [
          "https://fonts.googleapis.com/css2?family=Single+Day&display=swap"
        ]
      }
    },
    {
      "name": "assets",
      "installMode": "lazy",
      "updateMode": "prefetch",
      "resources": {
        "files": [
          "/assets/**",
          "/media/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"
        ]
      }
    }
  ],
  "dataGroups": [{
    "name"  : "posts",
    "urls": [
      "https://jsonplaceholder.typicode.com/posts"
    ],
    "cacheConfig": {
      "maxAge": "6h",
      "maxSize": 5,
      "strategy": "freshness",
      "timeout": "10s"
    }
  }]
}

截图说明

  • 在线状态首页:页面正常渲染,内容显示完整
  • 在线状态/browser页面:/posts接口数据正常加载展示
  • 离线状态数据未加载:切换离线模式后,页面提示无网络,数据区域为空
  • 离线重载时网络标签页:请求均显示失败,返回离线错误状态
  • 离线未重载时网络标签页:接口请求无法完成,无缓存数据返回

针对Angular 17的解决方案

1. 调整Service Worker启用逻辑

当前配置enabled: isDevMode()会在开发模式下启用SW,但Angular开发服务器(ng serve)默认会绕过Service Worker的缓存机制,导致缓存不生效。建议:

  • 生产环境测试:执行ng build --prod构建生产包,用静态服务器(如npx http-server dist/your-project-name)启动测试
  • 若需开发模式测试,修改启用条件为enabled: !isDevMode(),仅在生产模式启用SW

2. 修改Service Worker注册时机

registerWhenStable:30000会等待页面稳定后30秒才注册SW,可能导致页面首次加载时SW未生效,无法缓存初始请求。改为立即注册:

ServiceWorkerModule.register('ngsw-worker.js', {
  enabled: !isDevMode(),
  registrationStrategy: 'registerImmediately',
  scope: '/'
})

3. 优化dataGroups缓存策略

当前使用freshness策略,优先尝试网络请求,超时10秒后才会使用缓存。离线时无网络,需等待超时才会读取缓存,导致页面先显示错误。建议:

  • 改为performance策略:优先使用缓存,后台再更新网络数据,适合离线场景
"dataGroups": [{
  "name"  : "posts",
  "urls": [
    "https://jsonplaceholder.typicode.com/posts"
  ],
  "cacheConfig": {
    "maxAge": "6h",
    "maxSize": 5,
    "strategy": "performance"
  }
}]
  • 若坚持使用freshness,可缩短timeout至1秒,减少等待时间

4. 修正base href配置

index.html中<base href="./">可能导致Service Worker的作用域异常,无法正确拦截根路径下的请求。改为:

<base href="/">

5. 验证缓存是否生成

构建生产包后,打开浏览器Application > Cache Storage,确认:

  • ngsw-cache-v1下存在app、assets和posts对应的缓存条目
  • https://jsonplaceholder.typicode.com/posts请求已被缓存

6. 确保HttpClient请求被SW拦截

Angular Service Worker只会拦截通过HttpClient发起的请求,若使用原生fetch或其他方式请求数据,SW无法缓存。确认页面中使用HttpClient获取posts数据。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 07:44:59