
What are we talking about?
Increasingly, the task arises to teach the frontend application to work offline. This means giving a web application the property of a mobile or desktop program — to function in the absence of an Internet connection, as well as in the event of server failure.
The goal is to protect the user from connection problems on his device. It would be a shame not to save the tables created in google docs due to the loss of wi-fi in the nearest fast food!
To do this, you need to initialize the application in the browser and then cache the resources minimum necessary for operation. After that, the application can be run from the cache in case of server unavailability.
')
The solution to the problem is as follows:
- the first time you visit a web page, get “static” resources from the server in the form of html, css, js files, sprites, etc .;
- caching resources on the client side using browser tools;
- in the future, when requesting the same files, to issue them from the cache if there is no connection to the server;
- update modified cached resources.
There is already a wonderful
article about this, but since then something has changed. Earlier, ApplicationCache technology was popular, which you can read about
here . There were a number of problems with ApplicationCache, this technology lacked flexibility and is currently outdated and not recommended for use.
Now CacheStorage is entering the arena, with which you can work in the ServiceWorker.
ServiceWorker
ServiceWorker is a new technology that allows you to run javascript code in the browser in the background - an analogue of services (services) in operating systems. ServiceWorker runs from a web resource and continues to work in the browser, regardless of the application that initialized it.
Often, the purpose of using ServiceWorker is to receive push notifications in the browser and control cached resources, the last is our case.
CacheStorage
CacheStorage is a container for storing network resource caches. The global CacheStorage object is available by the name of caches. Its components are objects of type
Cache .
Cache is a named store of pairs: the Request object is the Response object. For each cached resource, the Cache instance will store the request and response created by the
fetch function.
How does it look in practice?
Now let's sort it all out on a small test application. Assume that the files are located on the local server at
localhost / test_serviceworker . We set the tasks. To manage caching, you must:
- create a serviceWorker that will work in the browser, regardless of the presence / absence of access to the network;
- put in caches the resources to be cached;
- in the serviceWorker code, hang up the handler for the fetch event - an event that occurs when a network resource is requested;
- build in the handler logic for issuing and updating the cache.
To start ServiceWorker, you first need to register it. In our application, you need to add the code as follows:
workerLoader.js
The next step is to write a simple ServiceWorker code.
appCache.js self.addEventListener('install', function(event) {
It is important to keep in mind that serviceWorker is in no way associated with the global scope of the application in which it was registered, and does not have a window object at all. In self, it has an object of type ServiceWorkerGlobalScope, on which event handlers are installed.
After taking actions and updating the page in chrome at
chrome: // inspect / # service-workers, you can see something like this:

In this screenshot, three js files are running in the browser in the background, the first of which is the caching service of this example.
Next, in the serviceWorker code, at the installation stage, we create the initial cache from the required resources.
appCache.js
Please note all links are relative to the root. Also among the cached resources there is no file workerLoader.js, which registers the serviceWorker. It is not desirable to cache it, since in offline mode the application will work without it. But if you urgently need to disable serviceWorker, problems may arise. Users will have to wait until the serviceWorker updates itself (by comparing the content).
Next, add the fetch event handler to the serviceWorker code. And on the request of the resource we give it from the cache.
appCache.js self.addEventListener('fetch', function(event) { event.respondWith(
But it's not always that simple. Let's say our static files have changed on the server. Let's complicate our code. Check the date of the last resource update by pulling the last-modified parameter from the HTTP headers. And if necessary, upload the latest version of the file and update the cache.
appCache.js
Note, the request and response clones are used to re-request. Only once it is possible to send a request and only once can it read the response. Because of this limitation, we create copies of these objects.
Similarly, the caching process can be controlled. Now there is a clear advantage over appcache manifest in its declarative style. The developer has the opportunity to operate HTTP headers, status codes, content and implement any logic for individual resources.
findings
- A significant plus is a flexible caching system. What and when to cache is all in our hands (say goodbye to ApplicationCache!).
- You should not use this technique for “non-static” resources, i.e. for data received from the server. It is better to do this not in the service, but inside the front-application at the model level and use, for example, localStorage.
- There is such a nuance: serviceWorker is allowed to download only via HTTPS or from a local server. An unpleasant restriction, but at the same time it is correct. HTTPS is becoming the standard for popular services.
- The main drawback. ServiceWorker and CacheStorage are both experimental technologies for the current time. And there is support for modern Mozilla, Opera and Google browsers. However, this is not enough .
The theme of web applications offline has been around for a long time. Perhaps ServiceWorker and CacheStorage is only a temporary solution. However, it already makes sense to use. Even if these technologies become obsolete, browser manufacturers will create something as a replacement. One has only to follow the progress in this direction!
The best materials for writing this article were:
http://www.html5rocks.com/en/tutorials/service-worker/introduction/ ,
https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers . Despite their presence, I decided to share information in Russian.