The Service Worker essentially acts as a proxy server between a web application, browser, and the network (when available). This API is designed to create efficient offline experiences by intercepting network requests and taking appropriate actions based on the availability of the network. It can update resources from the server, provide entry points for push notifications, and access background sync APIs.
The Service Worker is essentially used for caching resources in the browser. However, it goes beyond just caching and further optimizes through the use of workers. It is based on the Web Worker of HTML5, which means it does not block the execution of the current JavaScript thread. Its main working principles are as follows:
In simple terms, the Service Worker is a background worker thread that runs continuously, serving as a service. It is well-suited for functionalities that do not require independent resource data or user interaction. The most common use case is intercepting and handling network requests. Here are some key points to note:
Web Worker, which is an independent thread separate from the JavaScript main thread, allowing resource-intensive operations to be executed without blocking the main thread.Web Worker.The Service Worker has other use cases as well, and the standard of Service Worker can be used to make web platforms more similar to native applications. Some of these use cases include:
Here is an example of a simple Service Worker application that can still be used when there is no internet connection. The relevant code can be found at https://github.com/WindrunnerMax/webpack-simple-environment/tree/simple--service-worker. In this example, a simple native Service Worker is implemented without using any libraries like Workbox. However, it is worth noting that writing a native Service Worker can be cumbersome and complex, so using libraries like Workbox can simplify the process. Before using a Service Worker, there are some important considerations:
Service Worker runs on a worker, which means it cannot access the DOM.Service Workers can only be hosted on HTTPS, although http can be used for local debugging on localhost.Service Worker is not available.First, use Node to start a basic web server. You can use the anywhere package, or any other server of your choice. After executing the command, you can access http://localhost:7890/. Additionally, it is recommended to restart the server after writing the relevant code. I encountered issues with caching before, including disk cache and memory cache, and they were resolved after restarting the server. Also, please note that the link to be opened is localhost, as the browser may not automatically open to localhost. If you want to clear the cache, you can click on Clear site data in the Storage section of the browser console under the Application tab. This will clear all the cache on the website. If you are using a server environment such as express or koa, you can also try using Service Worker to cache data requests. Simply provide the path for the data request.
Create an index.html file and an sw.js file, and import the relevant resource files. The directory structure is as follows, and you can refer to https://github.com/WindrunnerMax/webpack-simple-environment/tree/simple--service-worker. Of course, you can directly clone and run a static file server to use it directly.
Simply import the relevant files in the html file, mainly to leverage the browser environment, and focus on the js section.
The first step in using Service Worker is to tell the browser to register a Service Worker script. In this case, we directly write it in the index.html file. By default, Service Worker only works for the root directory /. If you want to change the scope, you can add a second parameter { scope: "/xxx"} when registering, or directly specify the path /xxx/sw.js during registration.
Once the registration is successful, the work of the Service worker script begins. The following code is written inside the service worker script. After registration, the install event will be triggered, and the service worker script needs to listen for this event. First, the name of the cache is defined, which serves as the key to identify this cache object. The urlsToCache array contains the data that will be cached. As long as the relevant path is provided, even data requests can be cached, not just resource files. However, this can only be done for Get requests, as determined by the Cache API. After that, the install process is carried out. The event.waitUntil can be understood as the function of new Promise, which means that it waits for the serviceWorker to start running before continuing with the subsequent code. The actual parameter it accepts can only be a Promise. According to the explanation on MDN, it is because some time is needed for oninstall and onactivate to complete. The service worker standard provides a waitUntil method, which is called when oninstall or onactivate is triggered. It accepts a promise, and until this promise is successfully resolved, functional events will not be dispatched to the service worker. After that, the cache identified by the key of CACHE_NAME is retrieved from caches, and then the path in the array is added to the cache using cache.addAll. When the page is first opened, the Service worker will automatically request the relevant data and cache it. The data requested using the Service worker will be displayed with a small gear icon in the Network tab of the Chrome console, making it easy to recognize.
Next is the activated phase. If it is the first time loading the sw, after installation, it will directly enter the activated phase. However, if the sw is being updated, the situation becomes more complicated. The process is as follows: First, the old sw is A, and the new sw version is B. B enters the install phase while A is still in working state, so B enters the waiting phase. Only when A is terminated can B replace A and start working normally. There are several ways to trigger the terminated state: 1) Closing the browser for a period of time. 2) Manually clearing the Service Worker. 3) Skipping the waiting phase during sw installation. After that, the activated phase is entered, and the sw starts working. In the activated phase, many meaningful things can be done, such as updating the key and value stored in the Cache. In the code below, any CACHE_NAME that is not in the whitelist will be cleared. A version control can also be implemented here, where previous versions need to be cleared. Additionally, the current related cache is checked.
Afterwards, it is the stage of intercepting requests. This stage is a crucial stage for the sw, used to intercept and proxy all specified requests, and perform corresponding operations. All caching operations are done in this stage. First, we intercept all requests. The initial conditional statement is used to prevent all requests from being intercepted and made within the worker. However, it can also be used without the conditional statement. Then, if a request matches a cache, the data is directly retrieved from the cache; otherwise, a new request is made using fetch. Additionally, if needed, we can cache all requests made without matching during the event response.
Console output when opened for the first time:
Console output when opened for the second time and onwards:
With this, we have completed a simple example. When the page is opened for the second time, we can disconnect the browser's network connection, such as by closing the file server or selecting Offline in the Network tab of the console. We can see that the page still loads normally without requiring a network service. Additionally, in the Size column of the relevant data in the Network tab, there will be a (ServiceWorker) indication, indicating that the resources are loaded from the cache data of the ServiceWorker. You can clone this example from https://github.com/WindrunnerMax/webpack-simple-environment/tree/simple--service-worker and run it.