JavaScript ETag,是一種HTTP頭部標(biāo)記,用于幫助瀏覽器檢測Ajax請求中資源的新鮮度。當(dāng)客戶端請求一個資源時,服務(wù)器通過計算資源的校驗和產(chǎn)生ETag,并在響應(yīng)頭中返回給瀏覽器。當(dāng)瀏覽器再次請求相同資源時,會將上次請求返回的ETag一同發(fā)送給服務(wù)器,服務(wù)器通過比對新的資源的校驗和和上次請求返回的ETag是否一致,從而判斷資源是否發(fā)生了變化。
舉個例子,如果一個網(wǎng)站有一個資源文件,文件名為“example.js”,當(dāng)用戶第一次訪問該網(wǎng)站時,瀏覽器會請求example.js,服務(wù)器會在響應(yīng)頭中帶上ETag標(biāo)記:
ETag: "32a8b"當(dāng)用戶再次訪問該網(wǎng)站時,瀏覽器會與上次相同,請求該資源,但這次會在請求頭中帶上上次返回的ETag標(biāo)記:
If-None-Match: "32a8b"如果這次請求中example.js文件沒有發(fā)生變化,服務(wù)器會響應(yīng)304 Not Modified,告訴瀏覽器直接使用緩存中的資源。這種機(jī)制能夠減少冗余請求,提高網(wǎng)站性能。
ETag標(biāo)記有多種形式,可以是任意字符串、數(shù)字或者是文件的內(nèi)容。常用的方式是使用文件內(nèi)容hash,比如MD5或SHA-1等。下面是一個文件內(nèi)容hash的計算例子:
const crypto = require('crypto'); const fs = require('fs'); const hash = crypto.createHash('sha1'); const input = fs.createReadStream('example.js'); input.on('readable', () =>{ const data = input.read(); if (data) { hash.update(data); } else { const etag = hash.digest('hex'); console.log(etag); } });
在上面的例子中,我們使用Node.js中的crypto庫,以SHA-1的算法計算了文件“example.js”的內(nèi)容hash值,并以HEX字符串的形式輸出。這個hash值就可以作為ETag標(biāo)記,由服務(wù)器返回給瀏覽器。
ETag標(biāo)記的計算需要消耗一定的計算資源,如果web站點中的資源較多,可能會給服務(wù)器帶來較大負(fù)載。因此,我們可以通過設(shè)置“Cache-Control”頭部標(biāo)記來告知瀏覽器資源的緩存時間。如果超過了緩存時間,瀏覽器會重新請求資源,而不是發(fā)ETag請求確認(rèn)資源是否變化。
除此之外,由于ETag標(biāo)記是影響Web性能的因素之一,一些Web性能優(yōu)化方法也會建議關(guān)閉ETag標(biāo)記。如果站點的資源更新頻率較低,并且內(nèi)容的變化并不會引起不可接受的用戶體驗,那么關(guān)閉ETag標(biāo)記可以提高Web性能,降低服務(wù)器負(fù)荷。