Firebase 托管 Flutter Web 应用程序未清除首次部署的缓存

Posted

技术标签:

【中文标题】Firebase 托管 Flutter Web 应用程序未清除首次部署的缓存【英文标题】:Firebase Hosting Flutter Web App not clearing Cache of first deploy 【发布时间】:2020-08-07 18:34:27 【问题描述】:

我们构建了一个 Flutter Web 应用并通过 Firebase 托管进行部署。不幸的是,我们在初始部署中没有配置任何缓存设置。

现在我们部署了更新版本的网站,但人们仍然会从第一次部署中看到旧网站。到目前为止我们尝试了什么:

添加版本号到我们的 index.html

<"script src="main.dart.js?version=1" type="application/javascript"></script>

在 index.html 的标头中添加元数据:

  <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
  <meta http-equiv="Pragma" content="no-cache" />
  <meta http-equiv="Expires" content="0" />

在我们的 firebase.json 中,我们添加了以下标头:

"headers": [
      
        "source": "**",
        "headers": [
          
            "key": "Cache-Control",
            "value": "max-age=10"
          
        ]
      
    ]

所有这些尝试都没有成功。我们认为问题在于较新版本的文件中没有这些条目。我们如何强制它更新到我们的最新版本?如果有帮助,我们甚至会考虑开设一个新的 firebase 项目。

非常感谢您的帮助!

【问题讨论】:

你能成功做到这一点吗? 【参考方案1】:

如果最近创建的项目具有 serviceWorkerVersion 元素,它会在编译时更新版本,我看到 Flutter 现在默认在 index.html 中包含此脚本:

<script>
var serviceWorkerVersion = null;
var scriptLoaded = false;
function loadMainDartJs() 
  if (scriptLoaded) 
    return;
  
  scriptLoaded = true;
  var scriptTag = document.createElement('script');
  scriptTag.src = 'main.dart.js';
  scriptTag.type = 'application/javascript';
  document.body.append(scriptTag);


if ('serviceWorker' in navigator) 
  // Service workers are supported. Use them.
  window.addEventListener('load', function () 
    // Wait for registration to finish before dropping the <script> tag.
    // Otherwise, the browser will load the script multiple times,
    // potentially different versions.
    var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
    navigator.serviceWorker.register(serviceWorkerUrl)
      .then((reg) => 
        function waitForActivation(serviceWorker) 
          serviceWorker.addEventListener('statechange', () => 
            if (serviceWorker.state == 'activated') 
              console.log('Installed new service worker.');
              loadMainDartJs();
            
          );
        
        if (!reg.active && (reg.installing || reg.waiting)) 
          // No active web worker and we have installed or are installing
          // one for the first time. Simply wait for it to activate.
          waitForActivation(reg.installing ?? reg.waiting);
         else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) 
          // When the app updates the serviceWorkerVersion changes, so we
          // need to ask the service worker to update.
          console.log('New service worker available.');
          reg.update();
          waitForActivation(reg.installing);
         else 
          // Existing service worker is still good.
          console.log('Loading app from service worker.');
          loadMainDartJs();
        
      );

    // If service worker doesn't succeed in a reasonable amount of time,
    // fallback to plaint <script> tag.
    setTimeout(() => 
      if (!scriptLoaded) 
        console.warn(
          'Failed to load app from service worker. Falling back to plain <script> tag.',
        );
        loadMainDartJs();
      
    , 4000);
  );
 else 
  // Service workers not supported. Just drop the <script> tag.
  loadMainDartJs();

【讨论】:

【参考方案2】:

试试这个:

在你的 Flutter 应用中,在 web 文件夹中的 index.html 中,在 src="main.dart.js 之后添加一个版本号

所以你的新行将如下所示:

&lt;script src="main.dart.js?version=1" type="application/javascript"&gt;&lt;/script&gt;

然后在每次构建之前将版本号增加到 2 等。

2021 年 6 月更新:在 index.html 中添加这一行作为正文中的最后一个脚本

【讨论】:

谢谢,我实际上并没有在文档中看到,只是假设新部署的正在替换来自终端的消息为 finalizing version...version finalizedreleasing new version...、@987654326 之前的那个@.. 刚才我意识到“版本..”哈哈。非常感谢 这对我不起作用。在更新之前仍然需要一两次刷新(没有区别)。【参考方案3】:

如果你不想使用 server worker 缓存,你可以提供--pwa-strategy=none。否则,应用程序将在新版本下载并重新访问页面后更新。

示例:

flutter build web --release --pwa-strategy=none

它将生成一个没有主体的服务工作者。这对于本地测试或在不需要 Service Worker 缓存功能的情况下很有用

默认设置为offline-first:尝试快速缓存应用程序外壳,然后在加载所有后续资产时延迟缓存。在对资产进行网络请求时,将首选离线缓存。

参考:

https://github.com/flutter/flutter/issues/71333#issuecomment-736732314 flutter help build web

【讨论】:

如果在此之前我已经正常构建 web,并且想要实现这个 -pwa-strategy=none,我是否必须先清除缓存才能使其工作?或者它会立即生效 @ali 你可以先运行flutter clean 除此之外,每次我想部署新版本时是否需要更改内部版本号? 不一定

以上是关于Firebase 托管 Flutter Web 应用程序未清除首次部署的缓存的主要内容,如果未能解决你的问题,请参考以下文章

如何更新在 Firebase 托管中部署的 Flutter Web 版本

Flutter Web 应用程序在部署到 Firebase 托管后返回空白页面

我的 Flutter web 在本地构建得很好,但在 firebase 托管中不起作用

带有 Firebase 托管的 Flutter web 无法从存储中加载图片

Firebase 托管 Flutter Web 应用程序未清除首次部署的缓存

使用 Firebase 托管部署我的 Flutter Web 应用程序后出现错误