最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Workbox service worker: Cannot use import statement outside a module - Stack Overflow

programmeradmin2浏览0评论

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('^'),
  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?

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?

Share Improve this question asked Dec 10, 2019 at 16:54 FelipeFelipe 7,39113 gold badges58 silver badges75 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 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

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 */); 
发布评论

评论列表(0)

  1. 暂无评论