Boopathi Rajaa
Boopathi Rajaa

Reputation: 4729

How do I use ServiceWorker without a separate JS file?

We create service workers by

navigator.serviceWorker.register('sw.js', { scope: '/' });

We can create new Workers without an external file like this,

var worker = function() { console.log('worker called'); };
var blob = new Blob( [ '(' , worker.toString() , ')()' ], {
    type: 'application/javascript'
});
var bloburl = URL.createObjectURL( blob );
var w = new Worker(bloburl);

With the approach of using blob to create ServiceWorkers, we will get a Security Error as the bloburl would be blob:chrome-extension..., and the origin won't be supported by Service Workers.

Is it possible to create a service worker without external file and use the scope as / ?

Upvotes: 16

Views: 8783

Answers (2)

Jeff Posnick
Jeff Posnick

Reputation: 56064

I would strongly recommend not trying to find a way around the requirement that the service worker implementation code live in a standalone file. There's a very important of the service worker lifecycle, updates, that relies on your browser being able to fetch your registered service worker JavaScript resource periodically and do a byte-for-byte comparison to see if anything has changed.

If something has changed in your service worker code, then the new code will be considered the installing service worker, and the old service worker code will eventually be considered the redundant service worker as soon as all pages that have the old code registered and unloaded/closed.

While a bit difficult to wrap your head around at first, understanding and making use of the different service worker lifecycle states/events are important if you're concerned about cache management. If it weren't for this update logic, once you registered a service worker for a given scope once, it would never give up control, and you'd be stuck if you had a bug in your code/needed to add new functionality.

Upvotes: 11

Boopathi Rajaa
Boopathi Rajaa

Reputation: 4729

One hacky way is to use the the same javascript file understand the context and act as a ServiceWorker as well as the one calling it.

HTML

<script src="main.js"></script>

main.js

if(!this.document) {
    self.addEventListener('install', function(e) {
        console.log('service worker installation');
    });
} else {
    navigator.serviceWorker.register('main.js')
}

To prevent maintaining this as a big file main.js, we could use,

if(!this.document) {
    //service worker js
    importScripts('sw.js');
else {
    //loadscript document.js by injecting a script tag
}

But it might come back to using a separate sw.js file for service worker to be a better solution. This would be helpful if one'd want a single entry point to the scripts.

Upvotes: 7

Related Questions