Understanding HTTP Caching: Strong and Conditional Cache with Node.js Examples
This article explains the fundamentals of HTTP caching, covering strong and conditional cache mechanisms, the relevant response headers, and provides practical Node.js/Express code samples to demonstrate how browsers handle cache validation and expiration.
Preface
HTTP caching is a crucial knowledge point for front‑end engineers. This article gives a complete walkthrough of the caching process, aiming to provide readers with a solid overall understanding after reading.
Strong Cache
Strong cache does not require a request to the server; the browser reads the locally stored resource. In Chrome the network status is 200. Strong cache is divided into Disk Cache and Memory Cache, controlled by the browser. Whether a response is strongly cached depends on three header fields: Expires, Cache‑Control and Pragma.
Expires
The Expires value is an HTTP date. The browser compares the current system time with this date; if the system time exceeds the date, the cache is considered stale. Its priority is the lowest among the three headers.
Cache‑Control
Cache‑Controlis introduced in HTTP/1.1 and can appear in both request and response headers. Common directives include:
max‑age: seconds after which the cache expires.
no‑cache: forces revalidation with the server.
no‑store: disables all caching.
private: only the end user may cache.
public: proxies and CDNs may cache.
must‑revalidate: cache may be used until it expires, after which revalidation is required.
Pragma
Pragmaonly supports the no‑cache directive, which has the same effect as Cache‑Control: no‑cache and the highest priority among the three headers.
Local verification of the three strong‑cache headers using Express:
const express = require('express');
const app = express();
var options = {
etag: false, // disable conditional cache
lastModified: false, // disable conditional cache
setHeaders: (res, path, stat) => {
res.set('Cache-Control', 'max-age=10'); // strong cache expires after 10 seconds
},
};
app.use(express.static(__dirname + '/public', options));
app.listen(3000);The first load sends a request, the response includes Cache‑Control: max-age=10. Subsequent loads within 10 seconds use the strong cache without a network request. After the timeout, the browser revalidates and the cache is refreshed.
Conditional (Negotiated) Cache
When strong cache expires or the request explicitly bypasses it, the browser may send If‑Modified‑Since or If‑None‑Match headers. If the server validates the resource as unchanged, it returns 304 Not Modified and the browser loads the cached copy. The response will contain Last‑Modified or ETag headers.
ETag / If‑None‑Match
An ETag is a hash that uniquely identifies a resource version. If the server’s file changes, the hash changes. The client sends If‑None‑Match with the previous hash; a match results in a 304 response. Weak validators start with W/ and only trigger when the content truly changes.
Last‑Modified / If‑Modified‑Since
Last‑Modifiedholds the file’s last modification timestamp. The client sends If‑Modified‑Since with that timestamp on subsequent requests. If the timestamps match, the server returns 304.
Local verification of conditional cache using Express (ETag enabled, Last‑Modified disabled):
const express = require('express');
const app = express();
var options = {
etag: true, // enable conditional cache
lastModified: false, // disable Last‑Modified based cache
setHeaders: (res, path, stat) => {
const data = require('fs').readFileSync(path, 'utf-8');
const hash = require('crypto-js').MD5(JSON.stringify(data));
res.set({
'Cache-Control': 'max-age=00', // bypass strong cache
'Pragma': 'no-cache', // bypass strong cache
'ETag': hash,
});
},
};
app.use(express.static(__dirname + '/public', options));
app.listen(4000);First request receives the generated ETag. Subsequent requests include If‑None‑Match; if the file content is unchanged, the server returns 304 even if the file’s modification time changed.
Compared with Last‑Modified, ETag solves two problems:
If a file changes more frequently than one second, Last‑Modified may incorrectly return 304.
If a file’s content does not change but its timestamp does, Last‑Modified may still return 304, which is undesirable; ETag avoids this.
Summary
In real‑world scenarios such as the official website of Zhengcai Cloud, static resources like images, infrequently changed JavaScript files, etc., use caching to improve page load speed. Understanding the full HTTP caching flow enables developers to verify and fine‑tune caching behavior with Node.js.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
政采云技术
ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
