Ekin Berk Bozkurt
CodeBrew
Published in
4 min readJul 1, 2023

--

Prevent cache in Flutter Web / Flutter web prevent cache

[Update: 20.09.2024] Dear developers, unfortunately, I haven’t had enough time to make the necessary improvements for the new Flutter versions (3.20 and above). However, I’d like to share a few resources that might interest you and speed up your research. I aim to complete my updates for Flutter 3.20 and above as soon as possible and share them with you.

Official Documentation

https://github.com/flutter/flutter/issues/149103 (Prio 3 & Triage)

https://github.com/flutter/flutter/issues/149031

How to prevent cache in Flutter Web

Hello developer, I hope you are doing well. Today’s topic is little bit confusing but do not worry, we’ll figure it out in 5 min :) As always our solution is simple and works like a charm!

Question 1: What is cache and why do browser store cache?

  • Browser cache is a temporary storage location on your device where web pages, images, scripts, and other resources are stored by your browser. When you visit a website, your browser downloads files like HTML, CSS, JavaScript, and images. Instead of downloading them every time, the browser saves copies in its cache. When you revisit the site, the browser checks the cache for the files. If they’re there and haven’t expired, it retrieves them from the cache, speeding up page loading.

Question 2: Why do people want to prevent/disable cache?

  • Sometimes, it becomes crucial to ensure that all content, including images and resources like style sheets, is fetched fresh every time. Surprisingly, these elements can be essential in certain scenarios.

Now that we know about the cache, let’s move on with the solutions for Flutter Web.

The solution is straightforward. In Flutter Web, the cache problem occurs in the script called main.dart.js located in the web/index.html file. To resolve this, simply append a number or variable to the end of these script.

Indeed, to avoid manually changing or increasing the value every time, Flutter provides a predefined value in the index.html file called “serviceWorkerVersion”. We can use this value instead of manually modifying it.

By using the “serviceWorkerVersion” provided by Flutter, we can achieve a dynamic solution where the version is automatically incremented instead of manually updating it each time.

Please note that the “serviceWorkerVersion” value will only be populated when you build the Flutter application. In the test environment (Debug Mode), this value will not be filled. Hence, it is essential to build the application to obtain the correct value for “serviceWorkerVersion”

First, navigate to your project and locate the web/index.html file. Once you’ve found it, return to this page and proceed to apply one of the following solutions.

Case 1: Newer version of Flutter

If we need to prevent cache problem in newer version of Flutter, we have to modify some scripts. Since the script “main.dart.js” does not exist by default, we need to add it ourselves.

Please note that any modifications made to the “flutter.js” script

<script src=”flutter.js” defer></script>

will not resolve this cache problem.

We need to alter “_flutter.loader.loadEntrypoint” and we need to add additional parameter: “entrypointUrl: “main.dart.js?v=” + serviceWorkerVersion

In the end, your script section should look like this:

<script>
window.addEventListener('load', function (ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
entrypointUrl: "main.dart.js?v=" + serviceWorkerVersion,
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
}
}).then(function (engineInitializer) {
return engineInitializer.initializeEngine();
}).then(function (appRunner) {
return appRunner.runApp();
});
});
</script>

With this small addition, the problem is solved! :)

Case 2: Older version of Flutter

If we need to prevent cache problem in older version of Flutter, we have to modify the value of “scriptTag.src” in web/index.html to the following: “scriptTag.src = ‘main.dart.js?v=’ + serviceWorkerVersion;”.

In the end, your script section should look like this:

<script>
var serviceWorkerVersion = null;
var scriptLoaded = false;
function loadMainDartJs() {
if (scriptLoaded) {
return;
}
scriptLoaded = true;
var scriptTag = document.createElement('script');
scriptTag.src = 'main.dart.js?v=' + serviceWorkerVersion;
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(
'service worker disabled...',
);
loadMainDartJs();
}
}, 4000);
});
} else {
// Service workers not supported. Just drop the <script> tag.
loadMainDartJs();
}
</script>

With this small change, the problem is solved! :)

In this way, we have seen how to prevent the “Cache” problem in Flutter with simple solutions. I hope these solutions have been helpful to you.

If you have read this article and would like to support me, don’t be shy — buy me a coffee! :) ☕☕☕

Buy me coffee!

Some links that helps me to write this article, I think you should see.

Thank you for your reading this article. If you have any further questions, feel free to comment and make sure to hit clap button :) See you soon developer :)

--

--

Ekin Berk Bozkurt
CodeBrew

I love to solve problems using codes that improves users lives on a major scale. More Information: ekinberkbozkurt.com