Customization of Service Worker
raymondsze opened this issue · 20 comments
Apart from offline support, service worker could be used for handling notification.
Seems in 1.0.0, there is no way to do this kind of customization.
sw-precache-webpack-plugin provide the 'importScripts' option to do that purpose.
offline-plugin also provide an option 'entry' for this purpose.
References
https://github.com/NekR/offline-plugin/blob/master/docs/options.md
goldhand/sw-precache-webpack-plugin#67
Right now, the importScripts configuration for Push Notifications should be possible by ejecting and then customizing the precache configuration.
Does that help? Or were you asking if there's a way to accomplish this without ejection.
We’re not planning to add configuration, but generally we’re open to add “conventional” hooks. For example we we call src/setupTests.js if it exists for tests. We could do something similar for other kinds of entry points if somebody writes up a proposal for how it should work.
Couldn’t you just check if src/serviceWorkerImportScripts.js exists and set the importScripts option to that file when it exists? Preventing one from being able to inject code into the service worker sounds a lot like not allowing the user to supply a custom src/App.js… (though I’m quite new to all this, so I don’t know if I know what I’m talking about).
I recently ported a web app from Polymer to React (create-react-app) and am running into what sounds like the same issue. My web app relies heavily on the ability to receive background notifications from GCM, which it does using a serviceworker.
I've had to rename my existing service worker to gcm-service-worker.js in order to be able to use it, but I would love to be able to use sw-precache-webpack as well. Not to mention that it's always generating the precache service-worker.js even when I don't want it.
It would be great if I could use my own worker in conjunction with sw-precache somehow, without ejecting. :)
Custom code should be in the public directory, as its being imported by the service worker at runtime, not at build time using importScripts method.
in config/paths.js I've added a check if file exists and appended to module.exports
const sWPrecacheImportScript = fs.existsSync(resolveApp('public/service-worker-import.js'))
? 'service-worker-import.js'
: undefined;
module.exports = {
//...
sWPrecacheImportScript: sWPrecacheImportScript,
};and added an option in config/webpack.config.prod.js:
module.exports = {
//...
plugins: [
//...
new SWPrecacheWebpackPlugin({
//...
importScripts: paths.sWPrecacheImportScript ? [paths.sWPrecacheImportScript] : undefined,
})
]
}Now contents of public/service-worker-import.js are imported by service worker and executed.
What do you think?
Are you proposing that change be implemented in create-react-app or just a solution for those who have ejected? If part of cra, then sounds good to me, I think.
Yes, I'm proposing it to be implemented in create-react-app, as it's a modification of core package.
The concept is similar to the usage of src/setupTests.js file (see docs): developer interested in such functionality just have to create a file.
I'm interested in opinions on implementation as I'm new to CRA and not an expert in service workers. /cc @jeffposnick, @addyosmani
My motivation is to include a listener for Push Notifications in service worker.
One thing I didn't mention is that the sw-precache package doesn't have an option to include scripts directly in outputted service-worker.js file and such implementation creates an extra request to get service-worker-import.js on first page load.
As the file is located in the public folder, it's not processed (minified) by plugins. It's possible to change that (and add more logic like swapping the %PUBLIC_URL% string or environment variables), but implementation would have to be more complex.
Another option is to intercept the request via backend and replace variables at runtime like described in docs Injecting Data from the Server into the Page.
In meanwhile third bullet point in documentation Making a Progressive Web App should state that it's possible to use push notifications only after ejection and tweaking SWPrecacheWebpackPlugin configuration by hand.
From my perspective, if c-r-a wanted to establish of convention of checking for a service-worker-import.js file in some standard path, and then using it in importScripts if it exists, that certainly sounds fine. It would be useful for both runtime caching and push notifications.
I'm mindful of the fact that c-r-a's goal is to minimize the amount of customization that could otherwise overwhelm developers, so @gaearon who should give final sign-off as to whether this proposal crosses the line.
I can't promise we'll get it in but I'm curious to look at a possible implementation.
We had a similar problem while working on a project recently and we didn't want to "eject". Instead, we created a little tool that allows you to append custom service worker code to the one generated by CRA. It's not an ideal solution but worked well for us.
Have a look here: https://github.com/bbhlondon/cra-append-sw
cra-append-sw is a great workaround, thanks!
I agree, all of this thread should be summarized in the docs. The docs make it sound like PWA is built in and ready to go, but it's only a limited version unless you want to eject.
I just published an npm package that can remove the SWPrecacheWebpackPlugin and replace it with Workbox webpack plugins, allowing you to fully generate the service worker or injecting the precache assets into a custom service worker - all without ejecting (albeit by using react-app-rewired).
Hopefully can be of some use until Workbox is integrated in c-r-a or for people that want config options/custom service worker without ejecting or forking! The default config should do the same as what the current master branch of c-r-a does.
i would love to see an entry point to append SW code, that being said, i think a potential change in docs to include basic how to for using https://github.com/bbhlondon/cra-append-sw would be great to direct devs to a workable solution until we can come up with something standard, @gaearon thoughts?
@tszarzynski Is it possible to exclude URLs from being cached with your code?
@jeffposnick Or perhaps the above already possible today in CRA without ejecting?
@CodeJjang Currently it is not possible. The script is pretty dummy really. I could possibly look into that though. I imagine I could add some logic to remove some entries form CRA service worker's precacheConfig array. Can you give me an example of what exactly you'd like to achieve?
@tszarzynski The most desirable feature is to be able to supply some config file which can customize the behaviour of the Service Worker. Most importantly, I'd love to be able to config an array of URLs or a regex for which the SW won't serve cache for.
I have a 3rd party authentication service which I use in a popup (redirected from within my server), and when the SW work and the popup is opened, it doesn't follow the redirect (but serves something from cache).
If the SW is off, then everything works.
@CodeJjang I'm not planning to add this functionality to the script as it's supposed to be a simple tool. But have a look at my comments in: tszarzynski/cra-append-sw#11 (comment)
I suggested a few possible solutions there.