Welcome to Star at Github
The cache
Data read is a technique for improving data read performance, widely used in software development, such as commonCPU
Cache, database cache, browser cache, etc.
Caching is one of the necessary means of Web front-end performance optimization, which can not only ensure that users get the latest resources in the first time, but also reduce network requests. Browser cache policies mainly include the following two types:
HTTP cache
ServiceWorker
HTTP cache
HTTP caching needs to be configured by the browser and server. For example, Nginx and Apache can set different HTTP caching policies. HTTP caching is mainly for static files in the browser and can be divided into mandatory caching and negotiated caching.
Mandatory cache
The mandatory cache policy is for the browser to decide whether to use the cache based on the expiration time of the resource. If the resource is found in the cache and has not expired, the cache resource is directly used with the status code 200. Otherwise, the request is made directly.
Mandatory caching is based on Expires and cache-control.
Expires
HTTP/1.0 allows you to set the cache time using the response header field Expires, which corresponds to a future timestamp.
expires: Thu, 06 Mar 2031 12:35:43 GMT
A fatal shortcoming of Expires is that it takes a server time, but the browser compares the local time to that time, which can lead to an error in time accuracy. In order to control resources more precisely, HTTP /1.1 added cache-control response header fields.
Cache-control
Cache-control is a new HTTP /1.1 response header field that controls browser caching.
Its common values are the following:
field | instructions |
---|---|
no-cache | Indicates that the negotiated cache is used, that is, each time before using the cache, the server must confirm whether the cache resources are updated. |
no-store | Disallow browsers and all intermediate caches to store response content |
public | Public cache, which can be cached by proxy servers and shared by multiple users |
private | Private cache, cannot be cached by proxy server, cannot be shared by multiple users |
max-age | A value in seconds that indicates the duration of the cache |
must-revalidate | When the cache expires, you need to verify the cache validity on the server |
The values can be combined:
cache-control: public, max-age=31536000
It is important to note that Expires and cache-control have max-age precedence over Expires; if they are present together, the browser will use the max-age value first.
Negotiate the cache
The negotiated cache policy is to send a request for each request, and the server compares the resources to determine whether to use local cache or new resources. The HTTP status returned by the request response is 304, indicating that the cache is still valid. The challenge of controlling caching is moving from the browser side to the server side.
There are two ways to control the negotiated cache:
Last-Modified
和If-Modified-Since
ETag
和If-None-Match
The last-modified and If – Modified – Since
The server determines whether the cache has expired by comparing resources. If the browser sends resources directly to the server for comparison, the network overhead is too high, and the value of caching is lost, so it is not desirable.
An easy way to determine this is to compare the modification time of both resources by the last-Modified response header field and if-Modified-since request header field.
The working process is as follows:
-
When the browser requests a resource for the first time, the server adds a last-Modified field to the response header that returns the resource. This field indicates the Last modification time of the resource on the server.
-
When the browser requests the resource again from the server, the request header is called if-modified-since, with the modification time returned by the server
-
If the request header is if-modified-since, the server determines whether the relevant resource has changed. If Not, 304 Not Modified is returned, and the resource content is Not returned. The browser uses the resource cache value. Otherwise, the resource content is returned normally and the last-Modified response header content is updated.
This method can determine whether the cache is invalid, but there are two problems:
-
Accuracy problem, last-modified time accuracy is seconds, if the modification occurs within 1 second, then the cache judgment may be invalid.
-
Accuracy problem. If a file is modified and then restored, the contents remain unchanged. In this case, the browser cache can continue to be used, but because the modification time has changed, it will also return the duplicate contents.
The ETag and If – None – Match
To address the accuracy and accuracy issues, HTTP provides another way to accurately determine the cache that does not depend on the modification time, but on the file hash value: the response header field ETag and the request header field if-none-match.
The working process is as follows:
-
When the browser requests a resource for the first time, the server adds an Etag field to the response header. The Etag field is the hash value of the resource.
-
When the browser requests the resource from the server again, it adds if-none-match to the request header, which is the value of the ETag field in the previous response header.
-
The server receives the request again and compares the if-none-match field with the hash value of the response resource. If the two values are the same, the resource has Not changed and 304 Not Modified is returned. Otherwise, the resource content is returned as normal, and the calculated hash value is put into the ETag field in the response header, regardless of whether it has changed.
There are also some problems with this method of cache comparison, which can be seen in the following two aspects.
-
Calculate the cost. Generating hash values is an expensive operation relative to reading file modification time, especially for large files. For accurate calculation, you need to read the entire file content. For performance considerations, only part of the file content is read, which is prone to errors.
-
Calculation error. HTTP does not specify how hash values are computed, and different servers may use different hash methods. The problem with this is that the Etag generated for the same resource may be different on two servers, so the cache hit ratio of using Etag is reduced for sites that use server clusters to process requests.
Note that Etag has a higher priority than last-Modified in the negotiated cache.
ServiceWorker
Service Workers can be understood as proxy servers between Web applications, browsers, and the network (when available). The main purpose is to implement offline caching, which intercepts network requests and takes appropriate action to update resources from the server based on whether the network is available. It also provides a portal to push notifications and access background synchronization apis.
Method of use
It can be divided into three steps:
- registered
- The installation
- Listening to the
The ServiceWorker script must be “registered” to load before using it.
if ('serviceWorker' in window.navigator) {
window.navigator.serviceWorker
.register('./sw.js')
.then(console.log)
.catch(console.error)
} else {
console.warn('Browsers don't support ServiceWorker! ')}Copy the code
For browser compatibility, check if the serviceWorker property exists in window.navigator and tell the browser the path to the serviceWorker script by calling the register function for that property.
After the browser obtains the ServiceWorker script, it parses it and installs it. You can listen for the installation by listening for the “Install” event, but this event is only triggered when the script is first loaded. To enable the script to listen for web requests from the browser, you also need to activate the script.
After the script is activated, we can intercept the request and load the cached resource by listening for the FETCH event.
Here is the content of the sw.js file “registered” above:
const CACHE_NAME = 'ws'
// Why is this array? Because we can listen to multiple resources
let preloadUrls = ['/index.css']
/* Listen for the install event, which is usually used to set your browser's offline cache logic */
self.addEventListener('install'.function (event) {
/* This method prevents serviceWorker */ from closing before caching is complete
event.waitUntil(
/* Create a cache version named CACHE_NAME */
caches.open(CACHE_NAME)
.then(function (cache) {
/* Specifies the content to cache. The address is the access path relative to the domain name */
returncache.addAll(preloadUrls); })); });/* Register fetch events to intercept site-wide requests */
self.addEventListener('fetch'.function (event) {
event.respondWith(
/* Return */ if the cache matches the requested resource
caches.match(event.request)
.then(function (response) {
// Return the cache resource directly
if (response) {
return response;
}
return caches.open(CACHE_NAME).then(function (cache) {
const path = event.request.url.replace(self.location.origin, ' ')
return cache.add(path)
})
.catch(e= > console.error(e))
})
);
})
Copy the code
This code first listens for the Install event, calling the event.waitUntil() function in the callback and passing in a Promise object. Event.waituntil is used to listen for multiple asynchronous operations, including cache opening and adding cache paths. If one of these operations fails, the entire ServiceWorker fails to start.
It then listens for the FETCH event, calls the function event.respondwith () inside the callback and passes in a Promise object. When the FETCH request is caught, Returns the result of the Promise object in the event.respondWith function directly.
In this Promise object, we match the current request object with caches. Match, and return the cached result if there is a match, otherwise the request result is returned and cached.
Use restrictions
- in
ServiceWorker
Cannot be accessed directlyDOM
But it can passpostMessage
Interface to send messages to communicate with the pages it controls; ServiceWorker
Only in the local environment orHTTPS
For use on websites;ServiceWorker
There are scope limits, oneServiceWorker
Scripts can only work on the current path and its subpaths;- Due to the
ServiceWorker
It’s an experimental feature, so there are some compatibility issues.
conclusion
Expires
和cache-control
的max-age
Priority overExpires
.Strong cache
Is of higher priority thanNegotiate the cache
.Negotiate the cache
,Etag
Priority thanLast-Modified
High.ServiceWorker
It can be used to achieve offline cache. The main implementation principle is to intercept browser requests and return cached resource files.