what isService Worker
Service Worker
In essence, it acts as a proxy server between the Web application and the browser, and also acts as a proxy between the browser and the network when the network is available. They are intended to, inter alia, enable the creation of an effective offline experience, intercept network requests and take appropriate actions based on whether the network is available and whether updated resources reside on the server. They also allow access to push notifications and background synchronizationAPI
.
-
Service Worker
The essence of is aWeb Worker
Which is independent ofJavaScript
The main thread, so it cannot be accessed directlyDOM
, also can’t directly accesswindow
Object, but,Service Worker
Accessiblenavigator
Object, you can also use messaging (postMessage) andJavaScript
The main thread communicates. -
Service Worker
Is a network agent, it can controlWeb
All network requests for the page. -
Service Worker
It has its own life cycle and is well used.Service Worker
The key is to flexibly control its life cycle.
Service Worker
The role of
- For browser caching
- Implement offline
Web APP
- Message push
Service Worker
Compatibility
Service Worker
Is an advanced feature of modern browsers, it depends onfetch API
、Cache Storage
、Promise
And so on, among them,Cache
ProvidedRequest / Response
The storage mechanism of object pairs,Cache Storage
Store multipleCache
.
Example
In understandingService Worker
Before the principle of, let’s look at a paragraphService Worker
Examples of:
self.importScripts('./serviceworker-cache-polyfill.js');
var urlsToCache = [
'/',
'/index.js',
'/style.css',
'/favicon.ico',
];
var CACHE_NAME = 'counterxing';
self.addEventListener('install', function(event) {
self.skipWaiting();
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
return cache.addAll(urlsToCache);
})
);
});
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
if (response) {
return response;
}
return fetch(event.request);
})
);
});
self.addEventListener('activate', function(event) {
var cacheWhitelist = ['counterxing'];
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.map(function(cacheName) {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});
Let’s start to analyze and uncover it one by one.Service Worker
The mysterious veil of:
polyfill
First look at the first line:self.importScripts('./serviceworker-cache-polyfill.js');
, introduced hereCache APIOne ofpolyfillThispolyfill
Support makes it possible to use it under a lower version of the browser.Cache Storage API
. Want to achieveService Worker
The function of, generally need to matchCache API
The proxy network requests to the cache.
InService Worker
In the thread, use theimportScripts
introducepolyfill
Scripts, aimed at compatibility with earlier versions of browsers.
Cache Resources List
AndCache Name
After that, use aurlsToCache
List to declare static resources that need to be cached, then use a variableCACHE_NAME
To determine the current cachedCache Storage Name
It can be understood here thatCache Storage
Is aDB
, andCACHE_NAME
It isDB
Name:
var urlsToCache = [
'/',
'/index.js',
'/style.css',
'/favicon.ico',
];
var CACHE_NAME = 'counterxing';
Lifecycle
Service Worker
Independent of browserJavaScript
The main thread has its own independent life cycle.
If you need to install it on the websiteService Worker
, you need to use theJavaScript
The following code is introduced into the main threadService Worker
.
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js').then(function(registration) {
console.log('成功安装', registration.scope);
}).catch(function(err) {
console.log(err);
});
}
Here, must pay attention tosw.js
The path of the file, in my example, is under the current domain root directory, which means that,Service Worker
And can act as a proxy for all requests of the current website ifService Worker
Be registered to/imaging/sw.js
Next, that can only be agent/imaging
Network request under.
Can be usedChrome
Console, view the current page ofService Worker
Situation:
After the installation is completed,Service Worker
Will experience the following life cycle:
- Download (
download
) - Installation (
install
) - Activate (
activate
)
- User access for the first time
Service Worker
When controlling a website or page,Service Worker
It will be downloaded immediately. At least every24
It will be downloaded once every hour. It may be downloaded more frequently, but every24
It must be downloaded once every hour to prevent bad scripts from taking effect for a long time. - After the download is complete, start the installation
Service Worker
In the installation phase, we usually need to cache some static resources that we have declared beforehandurlsToCache
Declare in advance. - After the installation is completed, activation will begin and the browser will try to download it.
Service Worker
The script file, after downloading successfully, will be linked to the previously cachedService Worker
If the script file is compared with the previous oneService Worker
The script file is different, proving thatService Worker
Has been updated and will triggeractivate
Events. Activation is complete.
As shown in the figure, isService Worker
The approximate life cycle:
install
After the installation is complete, try caching some static resources:
self.addEventListener('install', function(event) {
self.skipWaiting();
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
return cache.addAll(urlsToCache);
})
);
});
First of all,self.skipWaiting()
Execute, inform the browser to skip the waiting phase directly and eliminate expired ones.sw.js
TheService Worker
Script, directly start trying to activate the newService Worker
.
Then usecaches.open
Open oneCache
, after opening, throughcache.addAll
Try caching our pre-declared static files.
Monitorfetch
, proxy network request
All network requests on the page will pass throughService Worker
Thefetch
Event trigger,Service Worker
viacaches.match
Try fromCache
If the cache hits, it will directly return to theresponse
Otherwise, create a real network request.
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
if (response) {
return response;
}
return fetch(event.request);
})
);
});
If we need to, in the process of request, toCache Storage
To add a new cache to thecache.put
Method to add, look at the following example:
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
// 缓存命中
if (response) {
return response;
}
// 注意,这里必须使用clone方法克隆这个请求
// 原因是response是一个Stream,为了让浏览器跟缓存都使用这个response
// 必须克隆这个response,一份到浏览器,一份到缓存中缓存。
// 只能被消费一次,想要再次消费,必须clone一次
var fetchRequest = event.request.clone();
return fetch(fetchRequest).then(
function(response) {
// 必须是有效请求,必须是同源响应,第三方的请求,因为不可控,最好不要缓存
if (!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
// 消费过一次,又需要再克隆一次
var responseToCache = response.clone();
caches.open(CACHE_NAME)
.then(function(cache) {
cache.put(event.request, responseToCache);
});
return response;
}
);
})
);
});
In the project, we must pay attention to the control of cache, interface requests are generally not recommended cache. Therefore, in my own project, there is no dynamic caching scheme here.
activate
Service Worker
There is always a need for a new day. With the iteration of versions, one day, we need to release the new version of the features online. At this time, we need to eliminate the old cache and the old one.Service Worker
AndCache Storage
How to eliminate it?
self.addEventListener('activate', function(event) {
var cacheWhitelist = ['counterxing'];
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.map(function(cacheName) {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});
- First of all, there is a white list
Cache
Is not eliminated. - After that, it passed
caches.keys()
Get everythingCache Storage
, the not in the white listCache
Elimination. - Elimination of use
caches.delete()
Methods. It receivescacheName
As a parameter, delete thiscacheName
All caches.
sw-precache-webpack-plugin
sw-precache-webpack-pluginIs awebpack plugin
, can be configured in thewebpack
Generate what we want when packagingsw.js
TheService Worker
Script.
One of the simplest configurations is as follows:
var path = require('path');
var SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
const PUBLIC_PATH = 'https://www.my-project-name.com/'; // webpack needs the trailing slash for output.publicPath
module.exports = {
entry: {
main: path.resolve(__dirname, 'src/index'),
},
output: {
path: path.resolve(__dirname, 'src/bundles/'),
filename: '[name]-[hash].js',
publicPath: PUBLIC_PATH,
},
plugins: [
new SWPrecacheWebpackPlugin(
{
cacheId: 'my-project-name',
dontCacheBustUrlsMatching: /\.\w{8}\./,
filename: 'service-worker.js',
minify: true,
navigateFallback: PUBLIC_PATH + 'index.html',
staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
}
),
],
}
In progresswebpack
After packaging, a file namedservice-worker.js
File for cachingwebpack
Packed static file.
One of the simplestExample.
Service Worker Cache
VSHttp Cache
Yes, compared withHttp Header
Cache,Service Worker
coordinateCache Storage
Also has its own advantages:
- Cache and update coexist: each update version, with the help of
Service Worker
You can use the cache to return immediately, but at the same time you can initiate a request to check if there is a new version update. - Non-invasive:
hash
The value is really too ugly. - Not easily washed away:
Http
Caches are easily flushed out and expire, whileCache Storage
It is not easy to be washed away. There is no saying about the expiration date. - Offline: with the help of
Service Worker
The off-line access application can be realized.
But the disadvantage is that due toService Worker
Depend onfetch API
Depend onPromise
、Cache Storage
Wait, compatibility is not very good.
SOA Anarchy Afterword
This article is only a brief summaryService Worker
The basic use and use ofService Worker
A simple way to do client caching, however,Service Worker
The role of the is far more than that, for example, with the help ofService Worker
Do offline applications, push for network applications (refer topush-notifications) etc.
Even with the help ofService Worker
, caching interfaces, in my project, is actually not so complicated. However, the advantage of doing interface caching is that it supports offline access and can normally access us when offline.Web
Application.
Cache Storage
AndService Worker
It’s always inseparable.Service Worker
The best use of is actually coordinationCache Storage
Do offline caching. With the aid ofService Worker
, can easily control network requests, and adopt different strategies for different network requests. For example, forCache
In fact, there are many kinds of situations. For example, the network request can be used preferentially, and the cache can be used again when the network request fails, or the cache and the network request can be used simultaneously. On the one hand, the request is checked, on the other hand, the cache is checked, and then whichever is faster is used.