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

Angular 5项目中用@angular/service-worker缓存Google Maps API失败求助

解决Angular 5 PWA无法缓存Google Maps瓦片的问题

我之前也踩过类似的坑,Angular Service Worker处理第三方动态资源(比如Google Maps的瓦片)确实需要针对性配置,给你几个实用的解决思路:

1. 精准配置dataGroups规则

你之前加了dataGroups但没生效,大概率是URL匹配模式不对。Google Maps的瓦片请求域名和路径有特定格式,得用通配符覆盖所有可能的请求:

打开你的ngsw-config.json,更新dataGroups部分:

"dataGroups": [
  {
    "name": "google-maps-resources",
    "urls": [
      // 匹配Maps的主JS脚本
      "https://maps.googleapis.com/maps/api/js/**",
      // 匹配所有瓦片请求(不同子域名如mt0、mt1等都要覆盖)
      "https://*.googleapis.com/maps/vt/**",
      // 可选:如果还有其他Maps相关资源(如标记图标)也加上
      "https://*.gstatic.com/maps/vt/**"
    ],
    "cacheConfig": {
      "strategy": "freshness", // 优先用网络,离线用缓存
      "maxSize": 2000, // 瓦片数量多,给足够的缓存空间
      "maxAge": "14d", // 瓦片不会频繁更新,缓存两周没问题
      "timeout": "3s" // 网络超时3秒就用缓存
    }
  }
]

配置完后一定要重新执行ng build --prod,Service Worker只在生产构建时生效。

2. 处理响应头限制

有些Google Maps的响应会带Cache-Control: no-cache或private头,这会阻止Angular Service Worker缓存。如果上面的配置还是没效果,就得用自定义Service Worker来手动缓存这些请求:

  1. 在项目根目录创建custom-sw.js,添加以下代码:
self.addEventListener('fetch', (event) => {
  const requestUrl = new URL(event.request.url);
  
  // 只处理Google Maps的瓦片请求
  if (requestUrl.hostname.includes('googleapis.com') && requestUrl.pathname.includes('/maps/vt/')) {
    event.respondWith(
      caches.open('google-maps-tiles')
        .then(cache => {
          // 先尝试网络请求,成功后缓存响应
          return fetch(event.request)
            .then(networkResponse => {
              cache.put(event.request, networkResponse.clone());
              return networkResponse;
            })
            // 网络失败时返回缓存的内容
            .catch(() => cache.match(event.request));
        })
    );
  }
});
  1. 修改angular.json里的Service Worker配置,让构建时包含这个自定义脚本:
"projects": {
  "your-project-name": {
    "architect": {
      "build": {
        "options": {
          "serviceWorker": true,
          "ngswConfigPath": "ngsw-config.json",
          "assets": [
            // 把自定义sw加入资源目录
            "src/custom-sw.js"
          ]
        }
      }
    }
  }
}
  1. 在app.module.ts里注册自定义Service Worker:
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';

@NgModule({
  imports: [
    ServiceWorkerModule.register('/custom-sw.js', { 
      enabled: environment.production,
      registrationStrategy: 'registerWhenStable:30000'
    })
  ]
})

3. 离线错误处理

你碰到的ERROR Error: Uncaught (in promise): Event报错,本质是离线时请求Maps资源失败但没有捕获Promise异常。可以在Maps初始化的代码里添加错误处理:

import { NgZone } from '@angular/core';

constructor(private ngZone: NgZone) {}

initMap() {
  if (navigator.onLine) {
    // 在线时加载地图
    this.ngZone.runOutsideAngular(() => {
      // 你的Maps初始化代码
    });
  } else {
    // 离线时显示提示
    alert('离线状态下无法加载地图,请检查网络连接');
    // 或者显示离线地图占位图
  }
}

测试注意事项

  • 每次修改配置后,一定要清空浏览器缓存(Chrome DevTools -> Application -> Clear storage)
  • 用ng serve --prod启动生产环境服务测试,开发环境Service Worker默认不启用
  • 在DevTools的Application -> Cache Storage里查看是否有google-maps-resources或google-maps-tiles的缓存条目

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 06:53:36