“Learned and forgotten.” If you leave a piece of knowledge unread for too long, the genetic fragment in your mind will become blurred, but the genetic index is still there. This article tries to help you memorize common knowledge points more deeply by combining practical theory. If there are any deficiencies, please correct them.
What is HTTP caching?
HTTP caching in plain English: when a client requests a resource from the server, it does not fetch the resource directly from the server (hello: server, give me the latest selfie picture). Instead, check to see if there are any resources in your storage that are still valid from the last time you saved them. If so, you save a lot of freight. Here’s a simple example:
- Client needs
a.js
A request header is sent(1kb)
- Returns after the server responds
a.js(10kb)
+ response headers(1kb)
- And over and over again
11kb
Traffic transmission
However, the content of the file A.js that we need often does not change, but still needs to waste traffic. In order to solve this problem, people put forward the concept of HTTP cache.
HTTP caching can be divided into strong caching and negotiated caching.
Strong cache
- Expires
- Cache-Control
- Pragma
Negotiate the cache
- Last-Modified
- If-Modified-Since
- ETag
- If-Not-Match
Strong cache vs. negotiated cache:
User: I need A.js now, please help me get the strong cache: wait a minute, LET me check if I have a backup of A.js, here it is. Negotiation cache: I also have a backup here, but I have to ask the server if this backup is the latest model, send request headers (1KB traffic). The server reply (1KB traffic) header uses local backup, and the latest data returned by the server is used in the case of a.js(10KB) and ringing headers (1KB).
Strong cache
Expires
This is an HTTP 1.0 field that represents the cache expiration time, which is an absolute time (current time + cache time). In the response header, the browser compares the current time with its value before requesting the resource and does not need to request it again if it has not expired.
A new cache. HTML
<! DOCTYPE html> <html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<link rel="icon" href="data:; base64,=">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>cache</title>
<script src="cache.js"></script>
</head>
<body>
<h1>cache</h1>
</body>
</html>
Copy the code
A new cache. Js
let http = require('http'),
fs = require('fs'),
path = require('path'),
url = require("url")
http.createServer((req,res)=>{
letpathname = __dirname + url.parse(req.url).pathname; // Get the file pathletStatusCode = 200 // response header statusCodeletExtname = path.extName (pathname) // Obtain the file name extensionlet headType = 'text/html'// Content typeif( extname){
switch(extname){
case '.html':
headType = 'text/html'
break;
case '.js':
headType = 'text/javascript'
break;
}
}
fs.readFile(pathname, function (err, data) {
res.writeHead(statusCode, {
'Content-Type': headType,
'Expires':new Date(date.now () + 10000).toutcString () // Set file expiration time to 10 seconds}); res.end(data); }); }).listen(3000) console.log("Server running at http://127.0.0.1:3000/");
Copy the code
Start the
node cache.js
Copy the code
Open a browser to http://127.0.0.1:3000/cache.html to check the network
- First access to all network request resources
- Reload from memory within 10s
from memory cache
)
- 10 seconds to close TAB, reopen the requested cache.html, load from disk (
from disk cache
)
- 10 seconds later, the cache is invalid. Repeat step 1
Disadvantages:
Expires
Expiration control is unstable. Because if we change the computer’s local time, the browser will determine that the cache is invalid.
Cache-control
This is an HTTP1.1 field, which is a relative time ‘cache-control ‘:’max-age=20’ meaning 20 seconds to use the cached resource without requesting the server
Fs. readFile(pathname,function (err, data) {
res.writeHead(statusCode, {
'Content-Type': headType,
'Cache-Control':'max-age=20'
});
Copy the code
Cache-control has many attributes in addition to max-age relative expiration time
1. No-store: no content is cached 2. No-cache: cache, but before using the cache, the browser will ask the server to determine whether the cache is up to date. 3. Both the public client and proxy server (CDN) can be cached. 4
See cache-Control for more attributes
If you have a few questions here, why setting Expires or cache-Control to cache.html doesn’t work in Chrome. Cache-control: max-age=0 indicates that the browser does not use the Cache.
Chrome does something quite different: ‘cache-control’ is always set to ‘max-age=0 ‘, no matter if you press enter, f5 or ctrl+f5. Except if you start Chrome and enter the url and press enter.
pragma
Pragma is a legacy field from prior HTTP /1.1 and is defined only as backward compatibility with HTTP. No discussion here. Those who are interested can click to learn about Pragma
The node hot update
Here if you think every time you modifycache.js
All files need to be re-executednode run cache.js
Here we can configure node hot update
npm init
npm i -D nodemon
Copy the code
NPM I -d stands for NPM install –save-dev
Modify the package. The json
"scripts": {
"dev": "nodemon ./bin/www"
},
Copy the code
We only need to run NPM run dev once
Comparison cache (negotiated cache)
The strong cache above still has a big flaw. When the set time expires, we have to ask the server for resources again, regardless of whether the file contents have changed. This is where the negotiation cache comes in.
Last-Modified
The response value returned by the server to the client regarding the most recent modification of the requested resource (GMT standard format)
If-Modified-Since
Request value sent by the client to the server for the last modification of the resource returned
The client saves the value and names it if-Modified-since. On a second request, the client sends an if-modified-since request to the server. The server compares the if-modified-since of the request header with the last-modified time of the server requested resource.
- If the resource has been modified: return the response resource
a.js(10kb)
+ response headers(1kb)
, status code:200 OK
- If not modified: only the response header is returned
(1kb)
, status code:304 Not Modified
// omit other codelet stat = fs.statSync(pathname);
fs.readFile(pathname, function(err, data) {// Check whether the file modification time of the request header is equal to the file modification time of the serverif(req.headers['if-modified-since'] === stat.mtime.toutCString ()) {// mtime is the timestamp of the file content change statusCode = 304; } res.writeHead(statusCode, {'Content-Type': headType,
'Last-Modified':stat.mtime.toUTCString()
});
res.end(data);
});
Copy the code
last-modified
If the resource is modified multiple times within 1s, the value is in secondslast-modified
No change, the client will still use the cache.- If the resource requested on the server (
a.js
) has been Modified, but the actual contents of the file have not changed at all. The last-modified time does not match, so it will be returned to the browser (example: the server dynamically generates the file).
To solve the problem, use the new fields ETag and if-none-match
ETag
Response value, a unique value calculated by the server to the client based on the contents of the file (GMT standard format)
If-Not-Match
Request value, sent by the client to the server to return the last resource unique value
The request process is the same as last-Modified
The above last_modified consists of mtime, whereas ETag consists of last_modified and content_length
Fs. readFile(pathname,function (err, data) {
let Etag = `${data.length.toString(16)}${stat.mtime.toString(16)}`
if((req.headers['if-modified-since'] === stat.mtime.toUTCString()) || (req.headers['if-none-match'] === Etag)) {
statusCode = 304;
}
res.writeHead(statusCode, {
'Content-Type': headType,
Etag
});
res.end(data);
});
Copy the code
Cache priority
When multiple caches exist at the same time, which one does the browser use? So you have a priority relationship here
- If strong cache and negotiated cache exist at the same time, the cache is forced if the strong cache is still in effect. Otherwise, negotiated cache is used. (Strong cache priority > Contrast cache priority)
- Strong cache
expires
andcache-control
When they coexist,cache-control
overwriteexpires
(cache-control
Priority >expires
Priority.) - Compared to the cache
Etag
andLast-Modified
When they coexist,Etag
overwriteLast-Modified
Effect. (ETag
Priority >Last-Modified
) priority.
Best practices
This is just to give you a better overview of HTTP caching, but how can we use caching to achieve a better user experience in the real world? Webpack everybody is believed to have no stranger, if the actual configuration experience students must remember our exports in the configuration file output or packaging picture filename tend to add hash | | chunkhash | | contenthash these fields
module.exports = {
output:{
path:path.resolve(__dirname,'.. /dist'),
filename:'js/[name].[contenthash:8].js',
chunkFilename:'js/[name].[chunkhash:8].js'
},
loader:{
rules:[
{
test:/\.(jep? g|png|gif)$/, use:{ loader:'url-loader',
options:{
limit:10240,
fallback:{
loader:'file-loader',
options:{
name:'img/[name].[hash:8].[ext]'}}}}}]}}Copy the code
The resulting file name is usually as follows
Finally, the impact of user behavior on the browser cache is included
Develop reading
Interview picks for HTTP caching