阿里云主机折上折
  • 微信号
Current Site:Index > Resource caching strategy design

Resource caching strategy design

Author:Chuan Chen 阅读数:42431人阅读 分类: 性能优化

Resource Caching Strategy Design

Resource caching is one of the key methods to enhance application performance, effectively reducing duplicate requests and network transfer time by leveraging browser caching mechanisms. Caching strategies need to be tailored based on resource type, update frequency, and business requirements.

Browser Caching Mechanisms

Browser caching is primarily divided into two categories: strong caching and协商缓存 (negotiation caching):

  1. Strong Caching: Uses local copies directly without sending requests to the server. Controlled via Cache-Control and Expires headers.
  2. Negotiation Caching: Validates resource expiration with the server on each request, implemented through Last-Modified/If-Modified-Since or ETag/If-None-Match.
// Strong caching example - Setting Cache-Control
app.get('/static/js/main.js', (req, res) => {
  res.setHeader('Cache-Control', 'public, max-age=31536000');
  res.sendFile('/path/to/main.js');
});

// Negotiation caching example - Using ETag
app.get('/api/data', (req, res) => {
  const data = getData();
  const etag = generateETag(data);
  
  if (req.headers['if-none-match'] === etag) {
    return res.status(304).end();
  }
  
  res.setHeader('ETag', etag);
  res.json(data);
});

Caching Strategy Classification

Static Resource Caching

Static resources like JS, CSS, and images typically adopt long-term caching strategies:

  • Filenames with hash values: main.a1b2c3d4.js
  • Set long-term caching headers: Cache-Control: public, max-age=31536000
<!-- Example of filenames with hashes -->
<script src="/static/js/main.a1b2c3d4.js"></script>
<link href="/static/css/styles.ef5g6h7i.css" rel="stylesheet">

Dynamic API Caching

API response caching requires more granular control:

  1. Short-term caching: Cache-Control: max-age=60
  2. Private caching: Cache-Control: private
  3. No caching: Cache-Control: no-store
// API caching strategy example
app.get('/api/user/profile', (req, res) => {
  // User profile data, cached for 1 minute and private only
  res.setHeader('Cache-Control', 'private, max-age=60');
  res.json(getUserProfile(req.user.id));
});

Service Worker Caching

Service Workers provide advanced caching control capabilities:

// Service Worker caching strategy example
const CACHE_NAME = 'v1';
const ASSETS = [
  '/styles/main.css',
  '/scripts/app.js',
  '/images/logo.png'
];

self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(ASSETS))
  );
});

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request)
      .then(response => response || fetch(event.request))
  );
});

CDN Caching Configuration

CDN caching needs to align with origin server strategies:

  1. Edge node cache duration settings
  2. Cache key rules (ignoring query parameters, request headers, etc.)
  3. Cache refresh mechanisms
# Nginx CDN caching configuration example
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
  expires 1y;
  add_header Cache-Control "public, no-transform";
  add_header X-Cache-Status $upstream_cache_status;
}

Cache Update Strategies

Versioned Filenames

Precise cache updates via content hashing:

// Webpack configuration example
output: {
  filename: '[name].[contenthash:8].js',
  chunkFilename: '[name].[contenthash:8].chunk.js'
}

Cache Purge Techniques

  1. Query parameter versioning: script.js?v=1.2.3
  2. Path versioning: /v1.2.3/script.js
  3. Server-initiated CDN cache purges

Caching Strategy Practical Cases

Case 1: E-commerce Product Images

location ~* \.(jpg|jpeg|png|webp)$ {
  # Long-term caching with version-based updates
  expires 1y;
  add_header Cache-Control "public";
  
  # Fallback to CDN origin when images are missing
  try_files $uri @cdn_fallback;
}

Case 2: Real-Time Data API

app.get('/api/stock/prices', (req, res) => {
  // Real-time data, caching disabled
  res.setHeader('Cache-Control', 'no-store, must-revalidate');
  res.setHeader('Pragma', 'no-cache');
  res.json(getRealTimeStockData());
});

Cache Monitoring and Optimization

  1. Monitor cache hit rates
  2. Analyze user access patterns
  3. Adjust cache duration strategies
// Cache hit rate monitoring middleware
app.use((req, res, next) => {
  const hit = res.getHeader('X-Cache-Hit');
  statsd.increment(`cache.${hit ? 'hit' : 'miss'}`);
  next();
});

Common Issue Solutions

Cache Pollution Issues

Solutions:

  1. Use Vary headers to handle content negotiation correctly
  2. Avoid overusing query parameters as cache keys
# Proper handling of content negotiation
location /api/data {
  proxy_cache_key "$scheme$request_method$host$uri$http_accept";
  proxy_cache_valid 200 10m;
  add_header Vary "Accept";
}

Mobile Caching Limitations

Mobile-specific handling:

  1. Appropriately shorten cache durations
  2. Consider local storage as a supplement
// Using localStorage as a cache fallback for mobile
function fetchWithCache(url) {
  const cached = localStorage.getItem(`cache:${url}`);
  if (cached) {
    return Promise.resolve(JSON.parse(cached));
  }
  
  return fetch(url)
    .then(res => res.json())
    .then(data => {
      localStorage.setItem(`cache:${url}`, JSON.stringify(data));
      return data;
    });
}

Advanced Caching Patterns

Cache-First Strategy

// Cache-first implementation
async function cacheFirst(request) {
  const cached = await caches.match(request);
  if (cached) return cached;
  
  const response = await fetch(request);
  const cache = await caches.open('v1');
  cache.put(request, response.clone());
  return response;
}

Network-First Strategy

// Network-first implementation
async function networkFirst(request) {
  try {
    const response = await fetch(request);
    const cache = await caches.open('v1');
    cache.put(request, response.clone());
    return response;
  } catch (e) {
    return await caches.match(request);
  }
}

Cache Security Considerations

  1. Avoid caching sensitive data
  2. Properly handle authenticated resources
  3. Prevent cache poisoning attacks
# Disable caching for sensitive data
location /api/account {
  add_header Cache-Control "no-store, must-revalidate";
  add_header Pragma "no-cache";
  proxy_pass http://backend;
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.