conclusion
1. The browser initiates an HTTP/HTTPS request for the first time to read resources from the server
2. The server sets response headers (cache-Control, Expires, Last-Modified, Etag) to the browser
2.1. Cache-control and Expires are strong caches, while Last-Modified and Etag are comparative caches (negotiated caches).
3, the browser does not close TAB, F5 refresh the page (again send a request to the server)
3.1. If cache-Control max-age and Expires do not exceed the cache time, all resources except index. HTML are loaded from memory cache. The status code is 200
3.2. If cache-Control’s max-age cache time is 5s and Expires Expires beyond 5s, cache-Control overwrites Expires
3.3 if the strong cache fails, the next step is comparison cache. The browser gets the response header from the second step and sets the a, if-modified-since value to the last-modified value of the response after refreshing the request. B. If-none-match is the Etag value of the response.
3.4 if both if-modified-since and if-none-match exist, then if-none-match takes precedence over if-modified-since. If the value of Etag is equal to the value of Etag in the second step, it will directly return a status of 304 and not return the content. If it is not equal, it will return a status code of 200 and return the content and cache-Control, Expires, Last-Modified, Etag and other response headers.
3.5 if if-modified-since exists and if-none-match does not, the procedure is similar to 3.4 above, except that the server compares if-modified-since with the value returned to the browser last-modified the first time
4. If the browser closes TAB. Re-open a new TAB and initiate a resource request. The steps are similar to above 3, except that in 3.1 above, the left and right resources are loaded from disk except for the index. HTML cache.
HTTP caches are divided into strong caches and contrast caches (negotiated caches)
1. Strong cache:
When requested, the client first accesses the cache database to see if the cache exists. Return if it exists, request the real server if it does not exist.
Forcing the cache to directly reduce the number of requests is the cache strategy that improves the most. Its optimization covers all three steps of requesting data mentioned at the beginning of this article. If caching is considered to optimize web page performance, mandatory caching should be the first consideration.
Fields that can cause forced caching are cache-Control and Expires
Expires
This is an HTTP 1.0 field that represents the cache expiration time, which is an absolute time (current time + cache time). Setting this field in the response header tells the browser that it does not need to request again until it expires.
Expires: Thu, 22 Mar 2029 16:06:42 GMT
const http = require('http')
const url = require('url')
const path = require('path')
const fs = require('fs')
http.createServer((req, res) => {
let { pathname } = url.parse(req.url, true);
console.log(pathname)
let abs = path.join(__dirname, pathname);
res.setHeader('Expires', new Date(Date.now() + 20000).toGMTString());
fs.stat(path.join(__dirname, pathname), (err, stat) = > {if(err) {
res.statusCode = 404;
res.end('not found')
return
}
if(stat.isFile()) {
fs.createReadStream(abs).pipe(res)
}
})
}).listen(3000)
Copy the code
The code above sets Expires to 20s.
-
First Request First request All outbound network requests
-
F5 refresh in 20s is currently loaded from memory. Because we didn’t close TAB, the browser added the cache application to the memory cache. (It takes 0ms, that is, within 1ms)
-
Close TAB within 20 seconds, open the requested URL, and load it from disk
Closing TAB clears the memory cache. But the disk cache is persistent, so all resources come from the disk cache. (It takes about 3ms, because the file is a bit small.) And comparing 2 to 3, it is clear that the memory cache is still much faster than the disk cache.
-
Request 20 seconds later, cache is invalid, repeat step 1
Disadvantages of expiration:
In this case, other computers accessing the server will cause the browser to determine that the cache is invalid if they change the local time: res.setheader (‘Expires’, new Date (date.now () + 2000000).togmtString ())
Cache-control
Given the shortcomings of Expires, in HTTP/1.1, a field, cache-Control, was added to indicate the maximum valid time for a resource Cache, during which a client does not need to send a request to the server
The difference between Expires and Cache-Control Expires sets absolute time. Cache-control sets relative timeCopy the code
Cache-control: max-age=20
- Cache-control: max-age = 20 max-age Specifies the maximum validity period
const http = require('http')
const url = require('url')
const path = require('path')
const fs = require('fs')
http.createServer((req, res) => {
let { pathname } = url.parse(req.url, true);
console.log(pathname)
let abs = path.join(__dirname, pathname);
res.setHeader('Cache-Control'.'max-age=20')
fs.stat(path.join(__dirname, pathname), (err, stat) = > {if(err) {
res.statusCode = 404;
res.end('not found')
return
}
if(stat.isFile()) {
fs.createReadStream(abs).pipe(res)
}
})
}).listen(3000)
Copy the code
This code sets the max-age to 20s for cache-control
First request -> Close TAB again to request a reference Expires graph
- No-cache tells the browser to ignore the cached copy of the resource, forcing each request to be sent directly to the server to pull the resource, but not “not cached”
- No -store mandatory cache does not retain any copy under any circumstances
- Public The cache of any path (local cache, proxy server) can cache resources unconditionally
- Private caches resources only for a single user or entity (different users, Windows)
Difference between no-store and no-cache
-
No-store: If no-store is set in the response of the server. Etag res.setHeader(‘ cache-control ‘, ‘no-store’) {Etag res.setHeader(‘ cache-control ‘, ‘no-store’);
-
No-cache If the server sets no-cache in the response, the browser compares the Etag before using the cache and returns 304 to avoid modification
Public and private
- If the parameter is set to public, the response can be cached by the user’s browser or any relay Web proxy. No write The default value is public, indicating that only the user’s browser can cache the private response.
2. Comparison cache (negotiated cache)
When the cache is forced to expire (for longer than a specified time), a comparative cache is used and the server decides whether the cached content is invalidated. Contrast caching can be used with force caching.
last-modified
1. The server returns the last-Modified field in the response header to the client to tell the client when the resource was last modified.
Last-Modified: Sat, 30 Mar 2019 05:46:11 GMT
2. The browser records the value and content in the browser’s cache database.
3. The next time the same resource is requested, the browser will pass the if-modified-since value in the request header to the server (which is the last-modified value in the first response header)
4. Compare the if-modified-since value of the request header with the last-modified value. If the value is equal, it indicates that the request header has not been modified, and the status code is 304. If not, it is modified, returns a status code of 200, and returns data
http.createServer((req, res) => {
let { pathname } = url.parse(req.url, true);
console.log(pathname);
let abs = path.join(__dirname, pathname);
fs.stat(path.join(__dirname, pathname), (err, stat) = > {if(err) {
res.statusCode = 404;
res.end('Not Fount');
return
}
if(stat.isFile()) {
res.setHeader('Last-Modified', stat.ctime.toGMTString())
console.log(stat.ctime.toGMTString())
if(req.headers['if-modified-since'] === stat.ctime.toGMTString()) {
console.log('if-modifined-since', req.headers['if-modified-since'])
res.statusCode = 304;
res.end()
return
}
fs.createReadStream(abs).pipe(res)
}
})
}).listen(3000)
Copy the code
Disadvantages of last-Modified:
- Last-modified is measured in seconds, and the cache cannot be used if the data may be modified several times within 1s.
- If the file is generated dynamically from the server, the update time is always the generation time, even though the file may not have changed, so it does not serve as a cache.
Etag
To solve this problem, a new set of fields, Etag and if-none-match, emerged
Etag is a unique value calculated from the contents of the file. The server stores the Etag field of the file. The subsequent process is the same as last-Modified, except that the last-Modified field and the update time it represents are changed to the Etag field and the file hash it represents, and if-modified-since becomes if-none-match. The server also compares and returns 304 on a hit and 200 on a miss. Etag has a higher priority than last-Modified
http.createServer(function(req, res) {
let { pathname } = url.parse(req.url, true);
console.log(pathname)
let abs = path.join(__dirname, pathname);
fs.stat(path.join(__dirname, pathname), (err, stat) = > {if(err) {
res.statusCode = 404;
res.end('Not Found')
return
}
if(stat.isfile ()) {//Etag the contents of the entity, which takes the contents of the file and calculates a unique value.let md5 = crypto.createHash('md5')
let rs = fs.createReadStream(abs)
letarr = []; Rs.on (rs.on);'data'.function(chunk) {
md5.update(chunk);
arr.push(chunk)
})
rs.on('end'.function() {
let etag = md5.digest('base64');
if(req.headers['if-none-match'] === etag) {
console.log(req.headers['if-none-match'])
res.statusCode = 304;
res.end()
return
}
res.setHeader('Etag', etag) // if-none-match is a pair of etag, if-none-match is browser, etag is server res.end(buffer.concat (arr))})}})}).listen(3000)Copy the code
Disadvantages of Etag:
- On each request, the server reads the index.html to verify that the file has not been modified
- 2. Etag a large file by combining the size of the file and the last modification time of the file