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

Angular16从Webpack转Vite后Service Worker哈希不匹配问题

问题:Angular 16 + esbuild 部署Firebase后Service Worker哈希不匹配报错

场景

把项目从Angular 15升级到16,同时把构建工具从Webpack换成esbuild(用@angular-devkit/build-angular:browser-esbuild构建器),通过Firebase Hosting部署后,Service Worker触发「Version_Installation_Failed」错误,所有资产都出现哈希不匹配问题。

错误日志

"Hash mismatch (cacheBustedFetchFromNetwork): https://myUrl.com/favicon.ico: expected 27d22f56faabc6ede22b52aad474a2806263ea9e, got a1b8ccd7e91b162f833472126c73929012a05ca7 (after cache busting)
Error: Hash mismatch (cacheBustedFetchFromNetwork): https://myUrl.com/favicon.ico: expected 27d22f56faabc6ede22b52aad474a2806263ea9e, got a1b8ccd7e91b162f833472126c73929012a05ca7 (after cache busting)
    at PrefetchAssetGroup.cacheBustedFetchFromNetwork (https://myUrl.com/ngsw-worker.js:474:21)

当前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.json", "/*.css", "/*.js"]
      }
    },
    {
      "name": "assets",
      "installMode": "lazy",
      "updateMode": "prefetch",
      "resources": {
        "files": ["/assets/**", "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"]
      }
    }
  ]
}

已尝试操作

  • 移除ngsw-config后重新部署
  • 删除所有资产后重新部署
    问题还是没解决。

需求

让所有用户自动重新下载最新资产,不用手动清除浏览器缓存。

当前版本检查代码

if (this.swUpdate.isEnabled) {
  this.subs.sink = this.swUpdate.versionUpdates.subscribe((update) => {
    console.log(update);
    if (!this.snackBar._openedSnackBarRef && update.type == "VERSION_READY")
      this.openSnackBar();
  });
}

解决办法

1. 改资产组名称强制刷新缓存

esbuild和Webpack生成哈希的逻辑不一样,旧Service Worker存的还是Webpack的哈希值,自然和新的对不上。直接改ngsw-config.json里的资产组名字就行——把"name": "app"改成"name": "app-v2","name": "assets"改成"name": "assets-v2"。Angular Service Worker会把名字变化当成全新的资产组,直接让客户端重新下载所有资源,旧缓存直接作废。

2. 规范构建和部署步骤

  • 部署前一定要清干净再构建:

    ng build --prod --output-hashing=all
    

    esbuild默认的哈希规则和Webpack不同,加上--output-hashing=all能确保所有静态文件(包括favicon)都带哈希后缀,避免Firebase的CDN缓存旧文件。

  • 给Firebase Hosting加缓存规则,让ngsw-worker.js和ngsw.json绝不缓存:
    编辑firebase.json,在hosting里加这段:

    {
      "hosting": {
        "headers": [
          {
            "source": "/ngsw-worker.js",
            "headers": [
              {
                "key": "Cache-Control",
                "value": "no-cache, no-store, must-revalidate"
              }
            ]
          },
          {
            "source": "/ngsw.json",
            "headers": [
              {
                "key": "Cache-Control",
                "value": "no-cache, no-store, must-revalidate"
              }
            ]
          }
        ]
      }
    }
    

    这样客户端每次都会拉最新的SW配置,不会用本地存的旧版本。

3. 主动触发SW更新检查

在应用启动时主动查更新,不用等SW自己轮询:
修改app.component.ts的ngOnInit:

import { SwUpdate } from '@angular/service-worker';

async ngOnInit() {
  if (this.swUpdate.isEnabled) {
    // 启动就主动查更新
    try {
      const hasUpdate = await this.swUpdate.checkForUpdate();
      if (hasUpdate) {
        // 有更新就直接激活,然后刷新页面
        await this.swUpdate.activateUpdate();
        window.location.reload();
      }
    } catch (err) {
      console.error('SW更新检查失败:', err);
    }

    // 监听版本就绪事件,自动激活刷新
    this.subs.sink = this.swUpdate.versionUpdates.subscribe((update) => {
      if (update.type === 'VERSION_READY') {
        this.swUpdate.activateUpdate().then(() => {
          window.location.reload();
        });
      }
    });
  }
}

这样用户打开应用就会自动检查更新,有新版本直接刷新,不用手动操作。

4. 清Firebase服务器端缓存

登录Firebase控制台,进Hosting的存储页面,点清除缓存,把CDN上存的旧资源清掉,避免返回旧文件导致哈希不匹配。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 23:05:01