Workbox service worker: Cannot use import statement outside a module
Asked Answered
T

2

24

I am creating a React App using the Create React App utility and I want to override the default service worker that it provides.

Since I don't want to eject my app, I am using the workbox-build package to create my service worker (I also used yarn to install the workbox-sw package).

My service worker code is the following:

/* eslint-disable no-restricted-globals */
import * as core from 'workbox-core';
import * as routing from 'workbox-routing';
import * as strategies from 'workbox-strategies';
import * as precaching from 'workbox-precaching';

self.addEventListener('message', event => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});

core.clientsClaim();

routing.registerRoute(
  new RegExp('^https://fonts.googleapis.com'),
  new strategies.StaleWhileRevalidate({
    cacheName: 'google-fonts-stylesheets-v1',
  })
);

precaching.precacheAndRoute([]);

routing.registerNavigationRoute(
  precaching.getCacheKeyForURL('/index.html'), {
    blacklist: [/^\/_/, /\/[^/?]+\.[^/]+$/],
  }
);

And my workbox-build script is:

const workboxBuild = require('workbox-build');

// NOTE: This should be run *AFTER* all your assets are built
const buildSW = () => {
  // This will return a Promise
  return workboxBuild.injectManifest({
    swSrc: 'src/service-worker.js',
    swDest: 'build/service-worker.js',
    globDirectory: 'build',
    globPatterns: [
      '**\/*.{js,css,html,png,json}',
    ]
  }).then(({
    count,
    size,
    warnings
  }) => {
    // Optionally, log any warnings and details.
    warnings.forEach(console.warn);
    console.log(`${count} files will be precached, totaling ${size} bytes.`);
  });
}

buildSW();

For registering the service worker I am using:

import { Workbox } from 'workbox-window';

export function register() {
  if ('serviceWorker' in navigator) {
    const wb = new Workbox('/service-worker.js');
    wb.register();
  }
}

However when I run my App I get these errors:

service-worker.js:2 Uncaught SyntaxError: Cannot use import statement outside a module
:3000/107/aggregator:1 Uncaught (in promise) TypeError: Failed to register a ServiceWorker for scope ('http://localhost:3000/') with script ('http://localhost:3000/service-worker.js'): ServiceWorker script evaluation failed

What am I doing wrong?

Tophole answered 10/12, 2019 at 16:54 Comment(0)
C
7

Current Answer

According to Mozilla's documentation it should work now, but keep an eye on the up-to-date implementation status in each browser. Firefox and Opera (implemented since Version 67) are still behind.

Mozilla is going to implement that feature in Firefox 114.


Original answer from 2020

There is no module support in workers yet.

importScripts() could do the job for you, but it can not import modules, meaning anything with an "export" keyword inside.

https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/importScripts

Contrayerva answered 26/3, 2020 at 10:47 Comment(1)
This means that the best solution is probably to compile that service worker, then move the compiled version into /public.Enmity
B
2

fips' answer helped me get on the right track.

I am not using a bundler/compiler. A bundler/compiler seems like a the avenue to pursue.

However, for anyone else that this may help:

importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.5.3/workbox-sw.js');

workbox.precaching.precacheAndRoute(self.__WB_MANIFEST);

fits well to those trying to solve some examples from Googles documentation

or more specific to your code, all those modules are accessible as attributes on the workbox object.

importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.5.3/workbox-sw.js');

self.addEventListener('message', event => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});

workbox.core.clientsClaim();

workbox.routing.registerRoute(/* your params here */);

workbox.precaching.precacheAndRoute(/* your params here */);

// presuming OP function is deprecated in current version and changed
// to 'registerRoute', but may actually be 'NavigationRoute' check
// current documentation for more clarity.
workbox.routing.registerRoute(/* your params here */); 
Biagio answered 28/5, 2022 at 1:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.