current position:Home>HTTP cache

HTTP cache

2022-04-29 15:36:18The wind blows and the clouds fly

Why use caching ?

        In front-end projects , It is a frequent action for the client to request the server to obtain data , If the same data is repeatedly requested , Then the number of redundant requests must cause a waste of bandwidth , And delaying the content to be processed by the browser rendering , So as to affect the user experience .
        The principle of caching is to save a copy of the response to the request resource after the first request , When the user initiates the same request again , If it is judged that the cache hit, the request is intercepted , Return a previously stored copy of the response to the user , So as to avoid re initiating resource requests to the server .

Mandatory cache

1. Use Expires Set expiration time

const http = require('http');
const fs = require('fs');
const url = require('url');

const server = http.createServer((req, res) => {
    const {
     pathname } = url.parse(req.url);
    if (pathname === '/') {
        const data = fs.readFileSync('./index.html');
    } else if (pathname === '/01.jpg') {
        const data = fs.readFileSync('./01.jpg');
            Expires:new Date('2022-2-19 21:50:00').toUTCString()
    } else {
        res.statusCode = 404


        from Expires It is not difficult to see in the judgment mechanism of forcing the cache to expire , There is a big loophole in this way , That is, it depends too much on the local timestamp , If the local time of the client is not synchronized with the time of the server , Or the client can actively modify the time , Then the judgment of cache expiration may not be consistent with expectations .
        In order to solve Expires The problem of , from HTTP1.1 The agreement began to add cache-control Field to Expires Expand and improve the functions of .

  'Cache-Control': 'max-age=5' // Start with the current time of the client , The unit is seconds 

If the data returned by the server is called entity , What is returned from the cache is called a copy . The above code means , After each entity return 5 Request the server again within seconds , All returned are copies , After that 5 Seconds before returning to the entity , In this cycle .

Cache-Control Other parameters of

no-chche And no-store( Mutually exclusive : You can't set... At the same time )

  • no-cache: Indicates that negotiation caching is enforced , That is, every time a request is made, it will not judge whether the forced cache expires , It is Negotiate with the server to verify the validity of the cache .
  • no-store: Indicates that any caching policy is prohibited , Each request from the client requires a new response from the server

private And public It is used to determine whether the response resources can be cached by the proxy server ( Mutually exclusive )

  • private: Limit the response resources to be cached by the browser .( Default )
  • public: Indicates that the response resource can be cached by the browser , It can also be cached by the proxy server
'Cache-Control': 'public,max-age=5'

max-age And s-maxage It is used to determine whether the response resources can be cached by the proxy server ( Mutually exclusive )

  • max-age: Set server expiration time
  • s-maxage: Set the proxy server expiration time , Only if the cache policy is public Effective when

Negotiate the cache

What do you mean : Before using the local cache , You need to send a request to the server , Negotiate with it whether the local cache saved by the current browser has expired .

    } else if (pathname === '/01.jpg') {
        const {
     mtime } = fs.statSync('./01.jpg');

        const ifModifiedSince = req.headers['if-modified-since']

        if (ifModifiedSince === mtime.toUTCString()) {
            // Caching works 
            res.statusCode = 304;
        const data = fs.readFileSync('./01.jpg');

        res.setHeader('last-modified', mtime.toUTCString())
        res.setHeader('Cache-Control', 'no-cache')

 Insert picture description here
We set... In the response body last-modified, After that, the client's request will bring a if-modified-since, We can use it to determine whether to go to the cache
* disadvantages : First, because it is judged according to the last modification timestamp of the resource . Although the file name has been modified , But it didn't change to the content , Negotiations will also fail . The second is the time stamp, which is in seconds , If the file modification speed is very fast ( millisecond ), Then it can't get the latest resources , This uses the resources in the cache , It eventually results in bug.

       Better negotiation caching scheme , The general meaning is that the server will hash the content of the resource to generate a unique string , As long as the content of the resource changes , The unique string will also change , To negotiate caching .

        const data = fs.readFileSync('./01.jpg');
        const etagContent = etag(data)

        const ifNoneMatch = req.headers['if-none-match']
        if (ifNoneMatch === etagContent) {
            res.statusCode = 304
        res.setHeader('etag', etagContent)
        res.setHeader('Cache-Control', 'no-cache')

* disadvantages : If the resources are relatively large , More , Frequent changes , So generation ETag The process will affect the performance of the server .

copyright notice
author[The wind blows and the clouds fly],Please bring the original link to reprint, thank you.

Random recommended