pwa
pwa copied to clipboard
Custom service worker
After diggin into this template I found out the SWPrecache plugin generates the service worker that's used in the build version. I have no clue how to edit this service worker when I want to edit the service worker and add push messaging. I was told maybe change de service-worker-prod.js in the build folder. But I assume files the build folder should generally not be changed? Please add a sw file where I can build my own service worker file instead of auto generating one.
You can update service worker source files generated by vue. It is a kind of basic uses
So I should edit my service-worker.js file in the dist folder? Whenever I run the command 'npm run build' it will be overwritten and loose my custom added stuff right?
@ragingwind the PWA template should definitely provide a way to add a user defined service worker, that's the whole point of PWAs. Maybe load the content of src/service-worker.js
as a callback in the service worker created by SWPrecache?
To ADD your custom code to the service-worker just import it with
importScripts
from the sw-precache-webpack-plugin
@Garito making that option work with the PWA template is a really frustrating path to go down. Contrary to what you'd expect, it has to be put into static/
instead of src/
because the vendor.js
file is not available of course.
All of this is not obvious, so I'd favor a documented and integrated method at best.
This template shows how to manage a service worker via sw-precache-webpack-plugin. So, using and extending options in sw-precache-webpack-plugin and sw-precache is that make sense to me. Not only for service worker, also there are configurations in build
, like a baseline of configurations which you can maintain or update anything what you want to update to fit your apps. For examples, if you want to copy your sw to specific place then you need to update CopyWebpackPlugin
I totally agree that document should provide more details but It's not easy. That is why we need your help.
There are two things I don't like about how it's done right now: 1.- I want the same service worker for every configuration I have (dev & prod for start but perhaps I would add test or some other) 2.- I would like to have all my important scripts in src and the rest outside it to allow me to copy only this folder and reconstruct my app (I'm thinking in the lack of a proper way to update libraries besides deleting the node_modules folder)
The documentation can be improved, I'm agree, but I manage to build a time tracker offline first without to much problems (besides my lack of knowledge of the thing that has become a monster but supercool to build)
Anyone figured out how to solve this?
- Write service-worker extension in es6, put it in src and have it compiled with babel
- Use it in importScripts
My current experiments either produce my extension with a webpackJsonp
that isn't understood in the context of the service worker or with a complete webpack bootstrap that expects window
to be present, which also doesn't work in the context of a service-worker.
I tried importScripts: [{chunkName: 'sw'}]
, importScripts: [{filename: 'sw.js'}]
, … with different combinations of
- adding it as an
entry
towebpack.base.conf.js
and not adding it asentry
- adding a CommonsChunkPlugin call with and without
minChunks: Infinity
It is darn frustrating. And there should really be a custom-service-worker.js
in src
with everything setup to just start coding.
If anyone explains to me the steps necessary to get this working, or if you can help me out with tips why my approaches keep failing, I promise to add a PR to this project that integrates it.
Here's a dirty workaround for anyone in need of writing an es6 custom service worker as an extension of the predefined service worker:
Add your es6 service worker as src/custom-service-worker.js
.
I'll list the necessary changes to webpack.prod.conf.js
, just update the relevant sections:
…
const babel = require('babel-core');
…
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
},
{
// copy custom service worker
from: path.resolve(__dirname, '../src/custom-service-worker.js'),
to: config.build.assetsRoot + '/[name].js',
transform: (content, path) => {
// and transpile it while copying
return babel.transformFileSync(path).code;
}
}
]),
// service worker caching
new SWPrecacheWebpackPlugin({
cacheId: 'survey',
filename: 'service-worker.js',
staticFileGlobs: ['dist/**/*.{js,html,css}'],
minify: true,
stripPrefix: 'dist/',
importScripts: [
{
// transformed custom-service-worker (es6 -> js)
filename: 'custom-service-worker.js'
}
]
})
Why did I do it that way?
You need Webpack to pick up on the service-worker somehow. If you add it as an entry, then all rules apply, which makes it unusable in the context of a service worker ( like window
being expected as part of the bootstrap).
You cannot simply require it, because it would then be part of your other js stuff, which is not what you want.
You only want to make it available, so I made use of CopyWebpackPlugin
. However, file loading rules wouldn't be triggered then, so I made use of the transform
option. That's where the dirty part comes in, by calling babel.transformFileSync
directly, which possibly misses any configurations for babel.
@tpraxl that seems to work quite well, however I'd also like to pass this through WebPack to get access to node modules. Using babel-core
only, it will just insert an import
directive for the Promise polyfill...
@Radiergummi Yeah, that's the drawback, that's why I consider it a dirty workaround. I had problems passing it through webpack and sharing common libs (e.g. wrapper for indexed-db). I used the CopyWebpackPlugin
to copy those libs and importScripts(…)
in the service worker itself.
I'd love to see a solution for that use case.
There is a hacky solution for React (reference as potential solution)
cra-append-sw: Utility tool to append custom code to ServiceWorker created by Create React App
Basically run another command after the build process to append the custom script: react-scripts build && cra-append-sw --mode dev ./custom-sw.js
Hey @tpraxl, I've implemented your solution but when I'm trying to use IndexedDB API (which is Promise-based), I get the following error
import _Promise from 'babel-runtime/core-js/promise';
Which means that babel-core isn't accessible from the service worker. I don't know if I misunderstood but you stated that it could be used with ES6 capabilities. Have I understood it wrongfully? Am I doing something wrong?
@amaralDaniel there is no build pipeline in place for your service worker file, so the import directive, the node_modules folder (which contains babel-runtime
) and other Webpack-based features are not available. You'd need to bootstrap these for yourself.
@tpraxl I LOVE YOU! <3