Reputation: 1223
I've a pretty large angular project that is built using webpack (I'm working with Microsoft's template of ASP.NET core). Is there any way I can use @angular/service-worker?
I've already tried adding the package and importing it, but the service worker never gets built. There's no error, but I get nothing. A new CLI project built with the flag works as expected.
Upvotes: 7
Views: 2534
Reputation: 7332
For non-cli projects built with webpack, you might not need using Angular Service Worker at all. Workbox is nice library for generating service workers which has a decent webpack plugin.
npm install --save-dev workbox-webpack-plugin
webpack.config:
import { GenerateSW } from 'workbox-webpack-plugin'
// const {GenerateSW} = require('workbox-webpack-plugin')
where at default it will generate service worker that precaches your webpack output with
plugins: [
// other webpack plugins
new GenerateSW()
]
You can then install this generated service worker after you are bootstrapping your angular application like:
platformBrowserDynamic().bootstrapModule(AppModule).then(() => {
if( !('serviceWorker' in navigator) ){
console.warn('Too bad, Service worker is not supported in current browser')
return
}
window.navigator.serviceWorker
.register(`/service-worker.js`, { scope: '/' })
.then(registration => console.log(`Service worker registration succeeded`))
.catch(error => console.log(`Service worker registration failed`))
})
provided that your server is serving from webpack's publicPath
. For more complex scenarios please refer to its docs: workbox-webpack-plugin, however, let me highlight few common scenarios here:
I. Precaching non-webpack assets
If you want to precache assets that are not managed by webpack, use globDirectory
and globPatterns
options to find them like:
new GenerateSW({
globDirectory: '.',
globPatterns: ['assets/**/*.{svg, png}']
})
Resulting glob asset url (which you can find in service-worker.js
self.__precacheManifest) will be resolved against glob directory, meaning your server should serve /assets/
.
II. Precaching server-generated assets
It's might be common that your index.html is server-generated, in which case you might want to use templatedUrl
to specify which routes to precache and how to revision retrieved assets. This is handy to use together with navigateFallback
to make sure we gracefully fallback to our index.html when accessing non-precached route.
new GenerateSW({
globDirectory: '.',
globPatterns: [],
templatedUrls: {
'/': ['templates/Index.html']
}
navigateFallback: '/'
})
templateUrl specify the route you want to precache and a glob-pattern to find a resource that will be used to revision the retrieved response from this URL. Make sure you have globDirectory
specified, otherwise plugin will fail with confusing error. As mentioned in workbox/issues/763, md5 hashes of files specified will be used to revision retrieved asset, which will be valid as long as /templates/Index.html
is not changing. Normally, if you use HtmlWebpackPlugin
to inject your bundle (with hash) into Index.html
template, service-worker.js
precache manifest revision will change as desired.
III. Cache API Responses on runtime
You might often want to also cache some API response and lets say user profile icons that appear in your site's dynamic content. In such we can use network-first strategy for our API to always fetch from the network if available and cache-first strategy for profile icons with something like:
new GenerateSW({
runtimeCaching: [{
urlPattern: /^http[s]*:\/{2}[\w.:-]+\/api\//,
handler: 'networkFirst'
}, {
urlPattern: /^http[s]*:\/{2}[\w.:-]+\/profile_icons\//,
handler: 'cacheFirst'
}]
})
Upvotes: 7
Reputation: 76
I was struggling with this as well since i'm not using the CLI. I managed to get it working by including these scripts in npm scripts.
"ngsw-config": "node_modules/.bin/ngsw-config dist src/ngsw-config.json",
"ngsw-copy": "cp node_modules/@angular/service-worker/ngsw-worker.js dist/",
"build-ngsw": "npm run ngsw-config && npm run ngsw-copy"
Include "build-ngsw" in your production build script.
The first script creates the ngsw.json file in your dist folder by reading the ngsw-config.json (which you'll have to create). The second script copies the actual angular service worker from @angular/service-worker to the dist folder.
Import and register the service worker. See step 3 in this tutorial Angular Service Worker Getting Started.
Upvotes: 6