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
之后添加一个版本号
所以你的新行将如下所示:
<script src="main.dart.js?version=1" type="application/javascript"></script>
然后在每次构建之前将版本号增加到 2 等。
2021 年 6 月更新:在 index.html 中添加这一行作为正文中的最后一个脚本
【讨论】:
谢谢,我实际上并没有在文档中看到,只是假设新部署的正在替换来自终端的消息为finalizing version...
、version finalized
、releasing 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-736732314flutter 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 无法从存储中加载图片