# Working with Service Workers
We're using Service Workers for two main purposes:
- To cache out static and dynamic data feeds, to make them available offline (opens new window)
- To run offline data sync.
To achieve the first point, we're using sw-precache (opens new window) from Google, and for the second, Vanilla JS with a little help from sw-toolbox (opens new window)
# Making things happen
The service-worker source code for vue-storefront
is pre-compiled with Babel presets and all is stored in an additional theme-specific Service Worker in src/{themename}/service-worker/index.js
. This file is attached to service-worker.js
generated by sw-toolbox
.
After changing anything in {themename}/service-worker/index.js
, despite you're in yarn dev
auto reloading mode, you need to do two things:
Recompile app (which regenerates service-worker):
yarn build
Reload Service Worker in Dev Tools (in Chrome, just click "Unregister" and reload the page, and a new Service Worker will be installed).
# Communication with the app
The application can speak to the Service Worker using the event bus, and only doing so. Please take a look at /core/lib/sw.js
where we have the following method:
export function postMessage(payload) {
if ('serviceWorker' in navigator && navigator.serviceWorker.controller) {
// check if it's properly installed
navigator.serviceWorker.controller.postMessage(payload);
return false;
} else {
// no service workers supported push the queue manualy
return true;
}
}
It allows you to send data to the Service Worker. For example, when the order is placed (/core/store/modules/checkout
):
/**
* Add order to sync. queue
* @param {Object} product data format for products is described in /doc/ElasticSearch data formats.md
*/
[types.CHECKOUT_PLACE_ORDER] (state, order) {
const ordersCollection = StorageManager.get('orders')
const orderId = entities.uniqueEntityId(order) // timestamp as a order id is not the best we can do but it's enough
order.id = orderId.toString()
order.transmited = false
order.created_at = new Date()
order.updated_at = new Date()
ordersCollection.setItem(orderId.toString(), order).catch((reason) => {
console.error(reason) // it doesn't work on SSR
sw.postMessage({ config: config, command: types.CHECKOUT_PROCESS_QUEUE }) // process checkout queue
console.info('Order placed, orderId = ' + orderId)
}) // populate cache
},