I wanted to ask "How to get the location of the service worker from the inside service worker?" but I've found this question get service worker id or date from within service worker, I was looking at the spec but didn't found anything useful.
So my question is are there any information about the service worker from inside the worker. Or to have any metadata I need to post a message to the worker.
I'm interested in the URL of the worker or the URL of the website where the worker was installed since I need this URL for routing inside the worker.
It seems that there is a location inside service worker that points to the URL of the worker filename.
To the path of the root where worker was installed (which is what I need) you can use:
const root_url = location.pathname.replace(/[^\/]+$/, '');
Related
I am using a SLURM cluster and want to be able to be able to add custom logs inside my task that should appear in the logs on the dashboard when inspecting a particular worker.
Alternatively I would like to be able to extract the name of the worker to use the log_event function and include the name of the worker in such a log in a way that matches the name on the dashboard.
The reason is so that I can see the logs of any long running workers that seem to be hanging or having issues.
I'm confused about what should be my scope property in my web manifest file.
Say, if my start_url is set to https://www.example.com/, should my scope be "/" or the same as start_url?
I'm using Vue3.
Note:
The main issue that I'm facing is the service-worker not getting detected by the browser and it figures out setting an appropriate scope could solve the problem it.
The scope field in the web app manifest defines something different than a service worker registration's scope.
Setting scope in your web app manifest is not required to use a service worker or have it detected.
If you could provide some more details about how you're registering your service worker in your question, we might be able to help you further. Additionally, "The service worker lifecycle" documentation has a lot of best practices for using service workers. I did want to share this answer to at least clarify the difference between those two scope values.
I have multiple pages in my application, for example, http://example.com/path/foo1.html and http://example.com/path/foo2.html. Can I register a separate service worker for each of these pages, or do they have to share the same service worker because they are both under ./path folder? In other words, does the scope setting specify a folder, or can scope specify a page? I tried separately registering service workers, one for each page, but what I am seeing is that both service workers are being loaded for each page. Is that expected, or am I doing something wrong?
You can register multiple service worker for different pages as long as the
scope specified is different. Since the root for both the pages is '/path',
everything after the path will be controlled by the same service worker.
For registering multiple service workers, you need the pages to be moved to different path. or atleast include something between root and html page.
path/samp/foo1.html and path/samp1/foo2.html
In above case, in foo1.html, you can register the service worker with scope as path/samp and in foo2.html, scope as path/samp1.
Enabling multiple service worker for the same scope is not currently available.
For more info: https://github.com/w3c/ServiceWorker/issues/921
I register service worker like this:
navigator.serviceWorker.register('/sw.js', {
scope: '/'
}).then(function(registration) {}).catch(function(err) {console.log(err)})
In production environment, I caught some errors like The request to fetch the script was interrupted. and The Service Worker system has shutdown.
What's the possible reasons for above errors?
There is a comment explaining them. I think it is useful. https://github.com/w3c/ServiceWorker/issues/1275
Its because the path to your service worker might not be correct. If your service worker is on the same level as the page which is trying to load the service worker then do navigator.serviceWorker.register('sw.js'}). /sw.js tries to load from the root of the project for e.g. http://localhost:8080/sw.js. Also look at network logs in the developer console to figure out the path the browser is using to fetch the service worker.
Suppose I provide a push notification service used by different websites. This service requires a service worker to be installed on my customers' sites. I want the architecture to have a few properties:
Completely static resources. The process of installing the service worker files and configuring the JS snippet, etc. only needs to be done once.
The ability to update the service worker at any time. I want to be able to update the service worker at any time to fix bugs, deploy improvements, etc.
Satisfying both of these constraints is difficult because the browser only installs a new version of the service worker if the content of service worker script itself changes. (That is, without considering dependencies specified via importScripts().)
If you can't change the contents of service worker itself, consider creating a "new" service worker by appending a hash to the service worker URL. This will cause the browser to install the "new" service worker every time the hash changes.
That is, replace code like
navigator.serviceWorker.register("/sw.js");
with
navigator.serviceWorker.register(`/sw.js?hash=${HASH}`);
When the "new" service worker is installed, the browser will re-check all imported scripts. (This applies even if the "new" service worker is byte-for-byte identical to the "old" one, because the URLs are different.)
How to generate the hash?
There's a few different ways to generate the hash. A completely random HASH will lead to the browser updating the service worker on every page load, which is unlikely to be what you want.
Two different approaches:
(Best) You know when the imported script changes. In this case, only change HASH when the imported script changes. Ideally, HASH would be a hash of the contents of the imported script itself.
(Okay) Derive the hash from the time. Math.floor(Date.now() / (3600 * 1000)) will cause a "new" service worker to be installed every hour, which will also result in the dependencies being checked. (You'll probably also want to apply some jitter to avoid all clients updating at the same time.)
Suggested architecture
If you provide a service-worker backed service to other websites (e.g. a push notification service), you can provide a completely static service worker and JS install snippet to your customers which allows you to control and trigger updates completely from your site.
Code for customer.com (all static):
JS snippet for customer to include on all HTML pages their site (static):
<script src="https://provider.com/register-sw.html?customer_id=8932e4288bc8">
</script>
Service worker for customer to install at https://example.com/sw.js (static):
importScripts("https://provider.com/imported-sw.js?customer_id=8932e4288bc8");
Code for your site (can be dynamic):
Service worker registration code on your site at https://provider.com/register-sw.html?customer_id=8932e4288bc8 (dynamic):
const HASH = hash_of_file("imported-sw.js");
navigator.serviceWorker.register(`/sw.js?hash=${HASH}`);
"Real" service worker on your site at https://provider.com/imported-sw.js?customer_id=8932e4288bc8 (dynamic):
// when service worker is updated, all clients receive
// update because service worker itself is "new"
self.addEventListener(...);
NOTE: The byte-for-byte requirement is in the process of being changed so that this check extends to imported scripts by default (not just the registered URL itself), but as of April 2017 no browser implements this behavior.