Blank Service worker script - javascript

The service worker script is blank
I am trying to implement service workers into my web app however i noticed nothing was working. I get confirmation that the service worker starts however when i try to view it in the chrome tools it shows a blank document. All efforts to console log etc are unsuccessful which is leading me to believe that the file is truly blank despite it obviously not being.
I have tried unregistered the service worker and updating manually.
SCRIPT ON INDEX
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw_basic.js')
.then(function(reg) {
// registration worked
console.log('Registration succeeded. Scope is ' + reg.scope);
}).catch(function(error) {
// registration failed
console.log('Registration failed with ' + error);
});
}
SERVICE WORKER SCRIPT
var CACHE_NAME = 'my-site-cache-v1';
var urlsToCache = [
'./', './index.php',
'./profile.php',
'./support.php',
'./img/dance3-min.png',
'./css/agency',
'./css/agency.min.css',
'./css/eventform.css',
'./css/loginmodal.css',
'./css/profile.css',
'./css/support.css',
'./css/table.css',
'./css/timer.css'
]
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Opened Cache');
return cache.addAll(urlsToCache);
})
);
});
self.addEventListener('fetch', function(event)) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
if (response) {
console.log('Successfully fetched resource from chache: ${event.request.url}');
return response;
} else {
console.error('Failed to fetch resource: ${event.request.url}');
}
return fetch(event.request);
}
)
)
}
EDIT* I have gotten it to update by changing the name of the js file and manually unregistering the service worker in chrome however it doesn't always update this way sometimes requiring several attempts
I still feel like there must be a better way for doing this and in all the tutorials / documentation it seems like it should install the new one and activate once all tabs are unloaded but its not even installing the updated one at all.
EDIT*
I noticed the service worker tries to install and then disappears.
Example- Service worker #12 is active and running. I refresh and then for a second service worker #24 is installing and then suddenly its gone. At this point i really don't know whats going on other feeds are saying its a problem with the cache max age but I have it set to 0 in the htaccess
Cache-Control: max-age= 0
EDIT*
I have tried taking the service worker onto a different page remove the caching and just try to get it to update.
Currently my index looks like
<html>
<head>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/beta/sw.js', {scope: '/beta/'})
.then(function(reg) {
// registration worked
console.log('Registration succeeded. Scope is ' + reg.scope);
}).catch(function(error) {
// registration failed
console.log('Registration failed with ' + error);
});
}
</script>
</head>
online page v2.0
</html>
and the service worker looks like
self.addEventListener('install', function(event) {
console.log("SW installed");
});
self.addEventListener('activate', function(event) {
console.log("SW activated");
});
self.addEventListener('fetch', function(event) {
console.log("Hijacked Signal");
event.respondWith(new Response("offline page"));
});
This Works when the user refreshes after visiting the page the text changes from online to offline. The problem occurs when i change the desired text (eg to offline 2.0). Anyone who has already visited the website is running the old service worker and so will see offline and not offline 2.0
a link to the page if anyone wishes to see whats going on
https://pakcollegelive.tk/beta/index.php

It turns out Cloudflare wasn't playing nice with the service worker files for whatever reason. It wasn't imperative that Cloudflare was used in my case so disabling it fixed the problem.

Related

Blazor - Service worker not installing due to integrity check failure

I'm trying to setup PWA for my blazor application. I followed the instructions on: https://learn.microsoft.com/en-us/aspnet/core/blazor/progressive-web-app?view=aspnetcore-6.0&tabs=visual-studio
But when I open the deployed website the following error occurs:
Failed to find a valid digest in the 'integrity' attribute for resource 'domain/manifest.json' with computed SHA-256 integrity 'uDWnAIEnaz9hFx7aEpJJVS1a+QB/W7fMELDfHWSOFkQ='. The resource has been blocked.
Unknown error occurred while trying to verify integrity.
service-worker.js:22
Uncaught (in promise) TypeError: Failed to fetch
at service-worker.js:22:54
at async onInstall (service-worker.js:22:5)
In the source file this happens here:
async function onInstall(event) {
console.info('Service worker: Install');
// Fetch and cache all matching items from the assets manifest
const assetsRequests = self.assetsManifest.assets
.filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url)))
.filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url)))
.map(asset => new Request(asset.url, { integrity: asset.hash, cache: 'no-cache' }));
await caches.open(cacheName).then(cache => cache.addAll(assetsRequests));
}
I think the error is happening since the entry in assetsRequests has a wrong hash and the resource is blocked. If I remove the file from the service-worker-assets.js, the service worker installs and the PWA can be used. But I think this is not a reliable solution.
This also happens sometimes for the appsettings.json. In the service-worker-assets.js I can find the following entry:
{
"hash": "sha256-+Py0\/ezc+0k1sm\/aruGPrVhS1jOCTfPKMhOSS+bunek=",
"url": "manifest.json"
},
So the hash does not seem to match. Where does the browser take the wrong hash from? How can I fix this so it does match?
Also it seems that the app is caching older files sometimes. Even when I do a "Reset Cache & Hard Reload" in Chrome the service-worker.js file is still an older version. Any idea how to fix this as well, since it might be related?
Edit: I was also checking this solution: https://stackoverflow.com/a/69935118/11385442. But in the mentioned blazor.boot.json I cannot find any reference to the manifest.json or the appsettings.json. Only Dlls are listed. So the problem only seems to relate to files not listed in blazor.boot.json.
Edit2: What I can see on the webserver is that the following files are published:
appsettings.json
appsettings.json.br
appsettings.json.gzip
So it seems like compressed version are added. Also the appsettings.json has a different size than the one in the solution. My guess is that somewhere in the build or release pipeline (Azure) the files are modified. But even when I copy the appsettings.json manually to the webserver the error still occurs. I was following Information provided here: https://learn.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/webassembly?view=aspnetcore-5.0
(Diagnosing integrity problems)
My guess was right. The appsettings.json was modified probably due to the xml transformation in the azure pipeline. My current solution is to exclude integrity validation for such resources as described in the following answer: Error loading appsettings.Production.json due to digest integrity issue
Also I changed the "sw-registrator.js" mentioned in the original posts comments to work correctly, because it didn't load the new files into the cache:
function invokeServiceWorkerUpdateFlow(registration) {
if (confirm("New version available, reload?") == true) {
if (registration.waiting) {
console.info(`Service worker registrator: Post skip_waiting...`);
// let waiting Service Worker know it should became active
registration.waiting.postMessage('SKIP_WAITING')
}
}
}
function checkServiceWorkerUpdate(registration) {
setInterval(() => {
console.info(`Service worker registrator: Checking for update... (scope: ${registration.scope})`);
registration.update();
}, 60 * 1000); // 60000ms -> check each minute
}
// check if the browser supports serviceWorker at all
if ('serviceWorker' in navigator) {
// wait for the page to load
window.addEventListener('load', async () => {
// register the service worker from the file specified
const registration = await navigator.serviceWorker.register('/service-worker.js');
// ensure the case when the updatefound event was missed is also handled
// by re-invoking the prompt when there's a waiting Service Worker
if (registration.waiting) {
invokeServiceWorkerUpdateFlow(registration);
}
// detect Service Worker update available and wait for it to become installed
registration.addEventListener('updatefound', () => {
if (registration.installing) {
// wait until the new Service worker is actually installed (ready to take over)
registration.installing.addEventListener('statechange', () => {
if (registration.waiting) {
// if there's an existing controller (previous Service Worker), show the prompt
if (navigator.serviceWorker.controller) {
invokeServiceWorkerUpdateFlow(registration);
} else {
// otherwise it's the first install, nothing to do
console.log('Service worker registrator: Initialized for the first time.')
}
}
});
}
});
checkServiceWorkerUpdate(registration);
let refreshing = false;
// detect controller change and refresh the page
navigator.serviceWorker.addEventListener('controllerchange', () => {
console.info(`Service worker registrator: Refreshing app... (refreshing: ${refreshing})`);
if (!refreshing) {
window.location.reload();
refreshing = true
}
});
});
}
else
{
console.error(`Service worker registrator: This browser doesn't support service workers.`);
}
Also I had to add this in service-worker.js:
self.addEventListener('message', (event) => {
console.info('Service worker: Message received');
if (event.data === 'SKIP_WAITING') {
// Cause the service worker to update
self.skipWaiting();
}
});
This code was mostly taken from https://whatwebcando.today/articles/handling-service-worker-updates/

ReactJS ServiceWorker storing the same code in multiple cache files

I am trying to add a serviceworker to an existing React app with this filesystem layout:
Filesystem
Basically a bit of initialization code is stored in the public folder, and all code of importance is in the src folder. In the serviceWorker.js file, I made an array of filenames to cache and call that array in the 'install' event listener, and if I check DevTools I can see that the filenames are present in the cache: when I preview the data in Chrome DevTools however, I see that the code inside the cached files is all from index.html. In fact, I can add anything I want to the filename array and I will find it in cached storage only to find that it is storing the index.html code. It seems like no matter what file I try to add to the cache, only index.html gets loaded.
ServiceWorker.js:
let CACHE_NAME = "MG-cache-v2";
const urlsToCache = [
'/',
'/index.html',
'/src/App.js',
'/monkey'
];
self.addEventListener('install', function (event) {
//perform install steps
event.waitUntil(
caches.open(CACHE_NAME).then(function (cache) {
console.log('Opened MG_Cache');
return cache.addAll(urlsToCache);
}).catch(function (error) {
console.error("Error loading cache files: ", error);
})
);
self.skipWaiting();
});
self.addEventListener('fetch', function (event) {
event.respondWith(caches.match(event.request).then(function (response) {
if (response) {
return response;
}
return fetch(event.request);
})
);
});
self.addEventListener('activate', (event) => {
event.waitUntil(async function () {
const cacheNames = await caches.keys();
await Promise.all(
cacheNames.filter((cacheName) => {
//Return true if you want to remove this cache,
//but remember that caches are shared across the whole origin
return;
}).map(cacheName => caches.delete(cacheName))
);
})
})
Portion of index.html:
<script>
if ('serviceWorker' in navigator)
{
window.addEventListener('load', function () {
navigator.serviceWorker.register('serviceWorker.js').then(function (registration) {
// Registration was successful
console.log("ServiceWorker registration successful with scope: ", registration.scope);
}, function (err) {
// registration failed :
(console.log('ServiceWorker registration failed: ', err));
});
});
}
</script>
Google Devtools Preview:
All files are the same
I have tried a variety of naming strategies in the filename array but all have ended with the same result. At this point I'm at a complete loss.
EDIT: While this does not solve my problem, I found an answer to another problem that gives a little guidance. It seems like the server never finds the file I request and thus returns index.html. I tried placing the serviceWorker.js file in the src folder and moving the service worker registration to App.js and got an error:
`DOMException: Failed to register a ServiceWorker for scope ('http://localhost:3000/src/') with script ('http://localhost:3000/src/serviceWorker.js'): The script has an unsupported MIME type ('text/html'). `
This suggests that the server somehow doesn't have access to the src folder, only public. Any idea why that may be?
An important piece of information I left out it that I'm using Create-React-App. Because of the enforced layout of the filesystem, the serviceWorker must be placed in the public folder: at the same time, the scope of service workers by default is the folder that they are placed in. According to this answer, changing the scope of the service worker to be a level above the folder that it is in requires adding to the HTTP header response of the service worker (not entirely sure what that means), and doing something like that assumes you have some form of a local server set up. Alas, thus far I have just been using npm start to test my app and pushing onto nsmp to make the site live, thus have negleted to do any form of server implementation myself (I know, not very smart of me).
My hotfix was to create a new temporary app with the npx create-react-app my-app --template cra-template-pwa command, copy all files pertaining to service workers from that app (serviceWorkerRegistration.js, service-worker.js, index.js, potentially setupTests.js), and paste them into my app. Then I could simply follow this tutorial. Now my site works offline.

Service worker cache storage not updated when code changes

My single page web application, is written as PWA. It's a ASP.NET Web API application, which is hosted under IIS. My application uses a service worker, which precaches my application shell. Other content is written to indexedDB or updated in the service worker cache on-the-fly, as the user clicks through the application.
I have a problem with code changes. When I update code, and refresh my browser, I can see my changes directly in the javascript and html code. When I go offline, my application falls back on the code, which is in my service worker. This code is still old code. It seems not to be updated, when i reload my application. My service worker looks like this:
const urlsToCache = ['.'
, 'index.html'
, 'favicon.ico'
, 'service-worker.js'
// More sources are cached here
];
self.addEventListener('install', function (event) {
console.log('\'Install\' event triggered.');
event.waitUntil(
caches.open(CACHE).then(function (cache) {
console.log('Application shell and content has been cached.')
return cache.addAll(urlsToCache);
}).then(function (event) {
return self.skipWaiting();
})
);
});
self.addEventListener('activate', function (event) {
console.log('\'Activate\' event triggered.');
return self.clients.claim();
});
For registering the service worker, my code looks like this:
navigator.serviceWorker.register('./service-worker.js')
.then(function (registration) {
console.log('Registered: ', registration);
registration.update();
console.log('Updated: ', registration);
resolve(registration);
}).catch(function (error) {
console.log('Registration failed: ', error);
reject(error);
});
So when the service worker get registered, it also checks for updates. However, it only updates when the service worker code itself is changed. Not when code within my application shell is changed without changing the service worker code itself.
How can i make sure that the code in my service worker is reloaded when I change my application code and refresh my page?

Service Worker is also Being cached in Chrome?

I built a Progressive Web App, https://www.tavest.com.
I don't understand why my service worker is also being cached in Chrome? https://www.tavest.com/service-worker-tavest.js So when I change the service-worker, the chrome doesn't detect the change thus the service worker is not updating.
Eventough I refresh the page many times, it's still the same. However, in Mozilla it works just fine.
Here's my code for installing the service worker
if ('serviceWorker' in navigator && (window.location.protocol === 'https:')) {
navigator.serviceWorker.register('/service-worker-tavest.js')
.then(function(registration) {
// updatefound is fired if service-worker.js changes.
registration.onupdatefound = function() {
// updatefound is also fired the very first time the SW is installed,
// and there's no need to prompt for a reload at that point.
// So check here to see if the page is already controlled,
// i.e. whether there's an existing service worker.
if (navigator.serviceWorker.controller) {
// The updatefound event implies that registration.installing is set:
// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-container-updatefound-event
var installingWorker = registration.installing;
installingWorker.onstatechange = function() {
switch (installingWorker.state) {
case 'installed':
// At this point, the old content will have been purged and the
// fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in the page's interface.
console.warn('New content is available, please refresh the page');
break;
case 'redundant':
throw new Error('The installing ' +
'service worker became redundant.');
default:
// Ignore
}
};
}
};
}).catch(function(e) {
console.error('Error during service worker registration:', e);
});
}
Thank you for your help
Warm regards,
It's because the service worker is just a normal JS file and it will be browser-cached.
You can set no-cache header to the /service-worker-tavest.js so that the browser will stop caching your service worker file. That way you can have your service worker updated immediately when the new file is uploaded.
Here is how to do that in Nginx:
location /service-worker-tavest.js {
# Don't use browser cache for service worker file
add_header cache-control "no-store, no-cache, must-revalidate";
}
I think I know the answer regarding to this caching.
It is because of "Service worker Lifecycle" in Chrome.
https://www.youtube.com/watch?v=TF4AB75PyIc
Conclusion: The cache in chrome browser is okay because chrome will update the service worker by itself.

Service worker throwing an net::ERR_FILE_EXISTS error?

service-worker.js:1 GET http://localhost:8080/service-worker.js net::ERR_FILE_EXISTS
This is the error I get every time I refresh after registering a service worker. I've made sure that the service-worker.js file exists in the root directory. Also the service worker is registered and working fine. But I still keep getting this error. Also I'm working on localhost.
This is my service-worker.js file:
console.log("SW startup");
var CACHE_NAME = "my_cache";
var urlsToCache = [
'./',
'./css/style.css',
'./js/script.js'
];
self.addEventListener('install', function(event) {
// Perform install steps
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.open(CACHE_NAME).then(function(cache) {
return cache.match(event.request).then(function (response) {
return response || fetch(event.request.clone()).then(function(response) {
console.dir(response);
console.log('hi');
cache.put(event.request.clone(), response.clone());
return response;
});
});
})
);
});
script.js file:
if (navigator.serviceWorker) {
console.log("ServiceWorkers are supported");
navigator.serviceWorker.register('service-worker.js')
.then(function(reg) {
console.log("ServiceWorker registered ◕‿◕");
console.dir(reg);
})
.catch(function(error) {
console.log("Failed to register ServiceWorker ಠ_ಠ");
console.dir(error);
});
}
I'm seeing the same issue. It can safely be ignored.
This bug tracks removing the noise from Chrome: https://code.google.com/p/chromium/issues/detail?id=541797
It should be live starting with Chrome 50.
From thread:
Improve error code for service worker bailing due to no update found
ServiceWorkerWriteToCacheJob is the URLRequestJob responsible for
fetching and writing the updated script. It fails with network error
when it wants to abort the update because the new script is the same
as the old one.
Currently that results in ERR_FAILED errors appearing in the DevTools
console and netlog, which is confusing and hard to debug because that
error also occurs for actual network errors. This patch changes the
error to FILE_EXISTS, so it's more clear why the job "failed".

Categories

Resources