5

I have Service Worker that load file from BrowserFS if the path contain __browserfs__, simplified code like this:

function loadDependecies() {
    self.skipWaiting().then(function() {
        if (!self.fs) {
            self.importScripts('https://cdn.jsdelivr.net/npm/browserfs');
            BrowserFS.configure({ fs: 'IndexedDB', options: {} }, function (err) {
                if (err) {
                    console.log(err);
                } else {
                    self.fs = BrowserFS.BFSRequire('fs');
                    self.path = BrowserFS.BFSRequire('path');
                }
            });
        }
    });
}
self.addEventListener('install', loadDependecies);

self.addEventListener('activate', loadDependecies);

self.addEventListener('fetch', function (event) {
    event.respondWith(new Promise(function(resolve, reject) {
        if (local) {
            console.log('serving ' + path + ' from browserfs');
            if (!self.fs) {
                (function loop() {
                    if (!self.fs) {
                        setTimeout(loop, 400);
                    } else {
                        serve();
                    }
                })();
            } else {
                serve();
            }
        } else {
            if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') {
                return;
            }
            //request = credentials: 'include'
            fetch(event.request).then(resolve).catch(reject);
        }
    }));
});

and when I didn't interact with the app for a while, open it again and then try to fetch local file It was keep loading probably because of the infinite loop, I've needed to reload the service worker by hand (using dev tools) to get the page.

So my question is how can I properly call importScripts to load BrowserFS in Service Worker?

jcubic
  • 61,973
  • 54
  • 229
  • 402
  • what do you want to achieve by calling `importScripts` inside the function? Why don't you load it right away? – smnbbrv Jul 01 '18 at 08:42
  • @smnbbrv because I need to call it in two events, if I call it outside it will be removed, I've read that you should not rely on global context in service worker and I can confirm the value that is added to self is removed in service worker life cycle. – jcubic Jul 01 '18 at 09:57

2 Answers2

1

I've ended up with this code, let is not added to global scope so it should be safe:

self.importScripts('https://cdn.jsdelivr.net/npm/browserfs');
let path = BrowserFS.BFSRequire('path');
let fs = new Promise(function(resolve, reject) {
    BrowserFS.configure({ fs: 'IndexedDB', options: {} }, function (err) {
        if (err) {
            reject(err);
        } else {
            resolve(BrowserFS.BFSRequire('fs'));
        }
    });
});

self.addEventListener('install', self.skipWaiting);

self.addEventListener('activate', self.skipWaiting);

self.addEventListener('fetch', function (event) {
    event.respondWith(fs.then(function(fs) {
        return new Promise(function(resolve, reject) {
            var url = event.request.url;
            var m = url.match(/__browserfs__(.*)/);
            if (m) {
                var path = m[1];
                if (path === '') {
                    return redirect_dir();
                }
                console.log('serving ' + path + ' from browserfs');
                serve();
            } else {
                if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') {
                    return;
                }
                //request = credentials: 'include'
                fetch(event.request).then(resolve).catch(reject);
            }
        });
    }));
});

EDIT it seems that this code also is wrong so I use this:

self.addEventListener('fetch', function (event) {
    let path = BrowserFS.BFSRequire('path');
    let fs = new Promise(function(resolve, reject) {
        BrowserFS.configure({ fs: 'IndexedDB', options: {} }, function (err) {
            if (err) {
                reject(err);
            } else {
                resolve(BrowserFS.BFSRequire('fs'));
            }
        });
    });
    ...
});

will see if this works. It may require to use importScripts in fetch.

jcubic
  • 61,973
  • 54
  • 229
  • 402
0

You probably want to statically build this file including the BrowserFS into it for more stable execution times.