How to register service worker using webpack?

Göran Lilja picture Göran Lilja · Dec 14, 2016 · Viewed 18.3k times · Source

I'm implementing a ReactJS web application using webpack and I want to start implementing a service worker to handle the network calls, in order to cache files. However, I find it hard to register the service worker javascript file. (I should add that I'm a beginner when it comes to both React and webpack.)

If I get it right, webpack merges every javascript file into one bundle.js file, which makes it hard to call navigator.serviceWorker.register('./sw.js').... I have tried different approaches, such as serviceworker-webpack-plugin, but without luck. If I follow the steps provided on the readme page, I get an error message saying Uncaught Error: serviceworker-webpack-plugin: It seems that your are importing "serviceworker-webpack-plugin/lib/runtime" without using the plugin. Makes sure that your webpack configuration is correct..

Here's my webpack.config.js file:

var webpack = require('webpack');
var path = require('path');
import ServiceWorkerWebpackPlugin from 'serviceworker-webpack-plugin';

module.exports = {
  devtool: 'inline-source-map',
  entry: [
    'webpack-dev-server/client?http://127.0.0.1:8080/',
    'webpack/hot/only-dev-server',
    './src/index.js'
  ],
  output: {
    path: path.join(__dirname, 'public'),
    filename: 'bundle.js'
  },
  resolve: {
    modulesDirectories: ['node_modules', 'src'],
    extensions: ['', '.js']
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: ['babel-loader'],
        query: {
          presets: ['es2015','react']
        }
      }
    ]
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new ServiceWorkerWebpackPlugin({
      entry: path.join(__dirname, 'src/sw.js'),
      excludes: [
        '**/.*',
        '**/*.map',
        '*.html',
      ],
      filename: 'sw.js'
    })
  ]
}

Note: I used the create-react-app command to get going. Also, I have no issues with the service worker itself, I have a working implementation for another web app. It's just registering it I'm struggling with.

Any help is appreciated!

Answer

Nicholas Lie picture Nicholas Lie · Jan 24, 2017

To remove the error, change the

import ServiceWorkerWebpackPlugin from 'serviceworker-webpack-plugin';

to

var ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin');

Also note that the documentation has a typo:

plugins: [
new ServiceWorkerWepbackPlugin({
  entry: path.join(__dirname, 'src/sw.js'),
}),
],

Notice that Webpack is spelled incorrectly here. It should be Webpack instead of Wepback.

Also, the docs stated that to register the Service Worker on main JS thread using the following code:

import runtime from 'serviceworker-webpack-plugin/runtime';

if ('serviceWorker' in navigator) {
  const registration = runtime.register();
}

However, upon closer inspection, it seems that the runtime directory is wrong. Checking the node_modules folder,

runtime location

It seems that the runtime.js is inside the lib folder. So, to fix this, change the

import runtime from 'serviceworker-webpack-plugin/runtime';

to

import runtime from 'serviceworker-webpack-plugin/lib/runtime';

Once I did this, I managed to get the Service Worker installed on my dev environment.

sw.js

I'm still learning React + Webpack though! Also still figuring out a way to use Service Worker properly in my React app. I've also informed the author of this plugin of these required changes in the documentation. Hope it helps others!