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!
Create a project with create-react-app and then do some changes in package. json for adding service worker in your project.
Workbox provides two webpack plugins: one that generates a complete service worker for you and one that generates a list of assets to precache that is injected into a service worker file. The plugins are implemented as two classes in the workbox-webpack-plugin module, named GenerateSW and InjectManifest .
Progressive Web Applications (or PWAs) are web apps that deliver an experience similar to native applications.
Workbox has a great support for it. In particular for the precache phase, there is the npm package workbox-webpack-plugin that contains a plugin called InjectManifest. This plugin is able to inject in the Service Worker code a variable named __WB_MANIFEST that contains a list of the entry points/generated files of the Webpack bundling process.
As of webpack 5, you can use Web Workers without worker-loader. The syntax was chosen to allow running code without bundler, it is also available in native ECMAScript modules in the browser. Similar syntax is supported in Node.js (>= 12.17.0):
serviceworker-webpack-plugin also provides a way for the serviceworker to see a list of all the bundle files it should cache, but that functionality is not available directly and requires making a webpack plugin to get.
Progressive Web Applications (or PWAs) are web apps that deliver an experience similar to native applications. There are many things that can contribute to that. Of these, the most significant is the ability for an app to be able to function when offline. This is achieved through the use of a web technology called Service Workers.
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 ServiceWorkerWebbackPlugin({
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,
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.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With