当前位置:网站首页>Practice examples to understand JS strong cache negotiation cache

Practice examples to understand JS strong cache negotiation cache

2022-07-04 20:28:00 1024 questions

Catalog

background

Lead to

Get ready

Launch page

HTTP Cache type

Strong cache

expires

cache-control

Negotiate the cache

Last-Modified,If-Modified-Since

Etag,If-None-Match

summary

background

Whether in development or interview ,HTTP Caching is very important , This is reflected in two aspects :

In development : Reasonable use HTTP Caching can improve the performance of front-end pages

During the interview :HTTP Caching is a high-frequency question in an interview

So this article , I don't talk nonsense , I'll go through Nodejs The simple practice of , The most easy to understand HTTP cache , Through this article, you will be able to understand and master it !!!

Lead to Get ready

Create folder cache-study, And prepare the environment

npm init

install Koa、nodemon

npm i koa -Dnpm i nodemon -g

establish index.js、index.html、static Folder

index.html

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="./static/css/index.css" rel="external nofollow" ></head><body> <div class="box"> </div></body></html>

static/css/index.css

.box { width: 500px; height: 300px; background-image: url('../image/guang.jpg'); background-size: 100% 100%; color: #000;}

static/image/guang.jpg

index.js

const Koa = require('koa')const fs = require('fs')const path = require('path')const mimes = { css: 'text/css', less: 'text/css', gif: 'image/gif', html: 'text/html', ico: 'image/x-icon', jpeg: 'image/jpeg', jpg: 'image/jpeg', js: 'text/javascript', json: 'application/json', pdf: 'application/pdf', png: 'image/png', svg: 'image/svg+xml', swf: 'application/x-shockwave-flash', tiff: 'image/tiff', txt: 'text/plain', wav: 'audio/x-wav', wma: 'audio/x-ms-wma', wmv: 'video/x-ms-wmv', xml: 'text/xml',}// Get the type of file function parseMime(url) { // path.extname Get the suffix of the file in the path let extName = path.extname(url) extName = extName ? extName.slice(1) : 'unknown' return mimes[extName]}// Convert the file to the format required for transmission const parseStatic = (dir) => { return new Promise((resolve) => { resolve(fs.readFileSync(dir), 'binary') })}const app = new Koa()app.use(async (ctx) => { const url = ctx.request.url if (url === '/') { // Access the root path and return index.html ctx.set('Content-Type', 'text/html') ctx.body = await parseStatic('./index.html') } else { const filePath = path.resolve(__dirname, `.${url}`) // Set type ctx.set('Content-Type', parseMime(url)) // Set transmission ctx.body = await parseStatic(filePath) }})app.listen(9898, () => { console.log('start at port 9898')}) Launch page

Now you can enter... In the terminal nodemon index, See the display below , It means that the service has been started successfully

At this point, you can enter... In the browser link http://localhost:9898/, Open and see the following page , It means that the page is accessed successfully !!!

HTTP Cache type

HTTP There are two common types of caching :

Strong cache : It can be determined by one of these two fields

expires

cache-control( Higher priority )

Negotiate the cache : It can be determined by one of these two pairs of fields

Last-Modified,If-Modified-Since

Etag,If-None-Match( Higher priority )

Strong cache

Next, let's talk about strong caching

expires

We just need to set the response header expires The time of is the current time + 30s That's it

app.use(async (ctx) => { const url = ctx.request.url if (url === '/') { // Access the root path and return index.html ctx.set('Content-Type', 'text/html') ctx.body = await parseStatic('./index.html') } else { const filePath = path.resolve(__dirname, `.${url}`) // Set type ctx.set('Content-Type', parseMime(url)) // Set up Expires Response head const time = new Date(Date.now() + 30000).toUTCString() ctx.set('Expires', time) // Set transmission ctx.body = await parseStatic(filePath) }})

Then we refresh the front page , We can see that there is one more in the response header of the requested resource expires Field of

also , stay 30s Inside , After we refresh , See the request is to go memory, It means , adopt expires The time effect of setting strong cache is 30s, this 30s within , Resources will go to the local cache , Instead of re requesting

Be careful : Sometimes you Nodejs Code update aging time , However, it is found that the front-end page is still on the time limit of the code , This is the time , You can put this Disabled cache Hook , Then refresh , Cancel... Tick again

cache-control

Actually cache-control Follow expires The effect is almost the same , It's just that the values of these two fields are different , The former sets the number of seconds , The latter sets the number of milliseconds

app.use(async (ctx) => { const url = ctx.request.url if (url === '/') { // Access the root path and return index.html ctx.set('Content-Type', 'text/html') ctx.body = await parseStatic('./index.html') } else { const filePath = path.resolve(__dirname, `.${url}`) // Set type ctx.set('Content-Type', parseMime(url)) // Set up Cache-Control Response head ctx.set('Cache-Control', 'max-age=30') // Set transmission ctx.body = await parseStatic(filePath) }})

There are too many response headers on the front-end page cache-control This field , And 30s Go to local cache in the , I won't ask the server

Negotiate the cache

Unlike strong caching , Strong caching is within the time limit , Don't go to the server , Only local cache ; The negotiation cache should go through the server , If you request a resource , When you go to the server , If it finds a hit cache, it returns 304, Otherwise, the requested resource is returned , Then how can fortune telling cache ? Let's talk about that

Last-Modified,If-Modified-Since

In a nutshell :

The first time a resource is requested , The server will take the last modification time of the requested resource as the response header Last-Modified Send the value to the browser and save it in the browser

The second time a resource is requested , The browser will treat the time just stored as the request header If-Modified-Since Value , To the server , The server obtains this time and compares it with the last modification time of the requested resource

If the two times are the same , It means that this resource has not been modified , That is hit cache , Then return 304, If it's not the same , It indicates that this resource has been modified , Cache misses , The modified new resource is returned

// Get file information const getFileStat = (path) => { return new Promise((resolve) => { fs.stat(path, (_, stat) => { resolve(stat) }) })}app.use(async (ctx) => { const url = ctx.request.url if (url === '/') { // Access the root path and return index.html ctx.set('Content-Type', 'text/html') ctx.body = await parseStatic('./index.html') } else { const filePath = path.resolve(__dirname, `.${url}`) const ifModifiedSince = ctx.request.header['if-modified-since'] const fileStat = await getFileStat(filePath) console.log(new Date(fileStat.mtime).getTime()) ctx.set('Cache-Control', 'no-cache') ctx.set('Content-Type', parseMime(url)) // Compare time ,mtime Is the last modification time of the file if (ifModifiedSince === fileStat.mtime.toGMTString()) { ctx.status = 304 } else { ctx.set('Last-Modified', fileStat.mtime.toGMTString()) ctx.body = await parseStatic(filePath) } }})

On the first request , In the response header :

On second request , Request header :

Because the resource has not been modified , Then hit cache , return 304:

At this point, let's modify index.css

.box { width: 500px; height: 300px; background-image: url('../image/guang.jpg'); background-size: 100% 100%; /* Modify here */ color: #333;}

Then let's refresh the page ,index.css Changed , So it will miss the cache , return 200 And new resources , and guang.jpg No modification , The hit cache returns 304:

Etag,If-None-Match

Actually Etag,If-None-Match Follow Last-Modified,If-Modified-Since Roughly the same , The difference lies in :

The latter is the last modification time of the comparison resource , To determine whether the resource has been modified

The former is to compare the content of resources , To determine whether the resource is modified

How do we compare the content of resources ? We just need to read the content of the resource , Turn into hash value , Just compare it before and after !!

const crypto = require('crypto')app.use(async (ctx) => { const url = ctx.request.url if (url === '/') { // Access the root path and return index.html ctx.set('Content-Type', 'text/html') ctx.body = await parseStatic('./index.html') } else { const filePath = path.resolve(__dirname, `.${url}`) const fileBuffer = await parseStatic(filePath) const ifNoneMatch = ctx.request.header['if-none-match'] // Production content hash value const hash = crypto.createHash('md5') hash.update(fileBuffer) const etag = `"${hash.digest('hex')}"` ctx.set('Cache-Control', 'no-cache') ctx.set('Content-Type', parseMime(url)) // contrast hash value if (ifNoneMatch === etag) { ctx.status = 304 } else { ctx.set('etag', etag) ctx.body = fileBuffer } }})

The verification method is the same as just Last-Modified,If-Modified-Since The same as , I won't repeat it here ...

summary

Reference resources  https://www.jb51.net/article/254078.htm

The above is the understanding of practical examples js Strong cache negotiate the details of cache , More about js For information about strong cache negotiation cache, please pay attention to other relevant articles on software development network !


原网站

版权声明
本文为[1024 questions]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/185/202207041835520969.html