Why Your Updated Frontend Code Isn’t Showing & How to Fix Cache Issues
This article explains why newly deployed front‑end pages often still display old content due to browser, Nginx, or CDN caching, and provides a three‑step method—including proper cache‑control headers, hash‑named assets, and version‑based fallback—to ensure users always see the latest version.
Introduction: Why Your Code Updates Are Ignored
Developers often wonder why a newly deployed version still shows the old page. The cause is usually browser and server caching, not missing uploads.
1. How Cache Tricks the Browser
1.1 Typical Symptoms
User reports page malfunction while local tests pass.
After refreshing, the index.html still references old JS/CSS files.
Network requests return 304 Not Modified or 200 OK from memory cache.
1.2 Main Culprits
Suspect
Method
Typical Quote
Browser cache
Keeps old file copies
"I just got this JS last week!"
Nginx default config
Missing proper cache headers
"I followed the rules, blame me?"
CDN cache
Global node sync delay
"Hold on, let me finish my tea"
2. Cache‑Control Response Headers
2.1 Strong vs Negotiated Cache
Strong cache : Browser uses local copy without contacting server.
Cache-Control: max-age=31536000 # cache for one yearNegotiated cache : Browser asks server if resource changed.
Last-Modified: Wed, 20 May 2024 08:00:00 GMT
ETag: "abc123"2.2 Core Principles
HTML files : Disable cache, always fetch fresh version.
Static assets with hash : Use long‑term cache with hash in filename.
Static assets without hash : Use short‑term cache.
# Build output example
/dist/index.html
/dist/logo.png
/dist/assets/main.3f7a8b.js
/dist/assets/style.abcd12.css
/dist/assets/hello.ac2314.png3. Three‑Step Solution
3.1 Step 1 – Precise Nginx Configuration
server {
listen 80;
server_name your-domain.com;
root /path/to/your/dist;
# 1. Long‑term cache for /assets/ (hashed files)
location ^~ /assets/ {
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable";
add_header X-Content-Type-Options "nosniff";
try_files $uri =404;
}
# 2. Short‑term cache for other static files
location ~* \.(js|css|png|jpg|gif|svg|webp|woff2?|ttf|eot|mp4|mp3|json|xml|txt|csv|wasm)$ {
if ($request_uri ~ "^/assets/") { break; }
add_header Cache-Control "public, max-age=3600, must-revalidate";
add_header X-Content-Type-Options "nosniff";
try_files $uri =404;
}
# 3. Disable cache for front‑end routes
location / {
add_header Cache-Control "no-store, no-cache, must-revalidate";
add_header Pragma "no-cache";
add_header Expires 0;
try_files $uri $uri/ @fallback;
}
# 4. Fallback to index.html
location @fallback {
rewrite ^ /index.html last;
}
}3.2 Step 2 – Build Hash‑Named Files
Configure the build tool to append a hash to filenames (e.g., main.
hash.js). When the file content changes, the hash changes, automatically invalidating the cache.
# Example output
/dist/assets/main.3f7a8b.js
/dist/assets/style.abcd12.css3.3 Step 3 – Version‑Number Fallback
Inject a version timestamp into HTML and generate version.json . At runtime, fetch the JSON and compare with the embedded version; if they differ, prompt the user to refresh. <code>/* checkVersion.ts (simplified) */ export const checkVersion = async () => { const metaTag = document.querySelector('meta[name="version-time"]'); const localVersion = metaTag?.getAttribute('content') ?? ''; const response = await fetch(`/version.json?t=${Date.now()}`, { cache: 'no-store' }); const { versionTime: latestVersion } = await response.json(); if (localVersion && latestVersion && localVersion !== latestVersion) { ElMessage('New version detected, click to refresh for a better experience.'); } };</code>
4. Verify Your Configuration
4.1 Quick Validation Commands
# HTML/route response (should disable cache)
curl -I https://your-domain.com/about
# Expected: Cache-Control: no-store, no-cache, must-revalidate
# Hashed static asset (should have long‑term cache)
curl -I https://your-domain.com/assets/main.3f7a8b.js
# Expected: Cache-Control: public, max-age=31536000, immutable
# Non‑hashed static asset (should have short‑term cache)
curl -I https://your-domain.com/logo.png
# Expected: Cache-Control: public, max-age=3600, must-revalidate4.2 Common Pitfalls
Forgot to reload Nginx after changes.
Mismatch between /assets/ path and actual build output.
CDN still serving stale copies.
Service workers interfering with cache.
5. Advanced Topics
5.1 Cache Isolation for API Proxy
location /api {
proxy_pass http://backend-server/api;
add_header Cache-Control "no-store";
add_header Access-Control-Allow-Origin "https://your-frontend-domain.com";
add_header Access-Control-Allow-Credentials "true";
}5.2 Security Headers
add_header X-Content-Type-Options "nosniff"; # Prevent MIME sniffing6. Summary
Proper cache management turns a performance boost into a reliable user experience; misuse leaves users stuck on outdated pages.
Respect cache, use versioning, and monitor alerts for safe deployments.
JD Tech Talk
Official JD Tech public account delivering best practices and technology innovation.
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.