阿里云主机折上折
  • 微信号
Current Site:Index > Cache strategy specification

Cache strategy specification

Author:Chuan Chen 阅读数:36314人阅读 分类: 前端综合

Caching strategies are a crucial means of front-end performance optimization, and reasonable engineering practices can ensure that caching mechanisms are efficient and controllable. From local storage to HTTP caching, different scenarios require targeted designs while avoiding common pitfalls.

Local Storage Standards

Local storage includes localStorage, sessionStorage, and IndexedDB, which are suitable for scenarios requiring persistence or large amounts of structured data. In engineering practice, clear naming conventions for storage must be established:

// Three-level naming convention: project prefix + module name + business key name
const STORAGE_KEY = 'PROJ_USER_TOKEN'; 
const HISTORY_KEY = 'PROJ_SEARCH_HISTORY';

// Encapsulate unified operation interfaces
export const storage = {
  set(key, value) {
    try {
      localStorage.setItem(key, JSON.stringify(value));
    } catch (e) {
      console.error('LocalStorage write failed', e);
      // Automatic fallback handling
      sessionStorage.setItem(key, JSON.stringify(value));
    }
  },
  get(key) {
    const data = localStorage.getItem(key) || sessionStorage.getItem(key);
    try {
      return data ? JSON.parse(data) : null;
    } catch {
      return data; // Compatible with non-JSON data
    }
  }
};

Capacity Control Strategies:

  • localStorage is typically limited to 5MB per domain.
  • Automatically clean up using the LRU algorithm when the threshold is exceeded.
  • Sensitive data must have an automatic expiration time.
// LRU cache implementation example
class LRUCache {
  constructor(maxSize) {
    this.cache = new Map();
    this.maxSize = maxSize;
  }
  
  get(key) {
    if (!this.cache.has(key)) return null;
    const value = this.cache.get(key);
    this.cache.delete(key);
    this.cache.set(key, value);
    return value;
  }
  
  set(key, value) {
    if (this.cache.size >= this.maxSize) {
      const oldestKey = this.cache.keys().next().value;
      this.cache.delete(oldestKey);
    }
    this.cache.set(key, value);
  }
}

HTTP Caching Strategy Design

HTTP caching is divided into strong caching and negotiated caching, with different strategies configured based on resource types:

Strong Caching Configuration Example (Nginx):

location ~* \.(js|css|png)$ {
  expires 365d;
  add_header Cache-Control "public, max-age=31536000, immutable";
}

Negotiated Caching for Dynamic Resources:

location /api {
  add_header Cache-Control "no-cache";
  etag on;
}

Cache Update Strategy Comparison:

Strategy Type Implementation Method Applicable Scenarios Example
Filename Hash Build tool generates hashed filenames Static resources app.3a7b8c.js
Query Parameter Versioning URL appends ?v=1.0.0 Third-party libraries lib.js?v=2.1.4
Path Versioning Versioned directory structure Multi-environment deployment /v2/assets/logo.png
Background Push Updates Service Worker control PWA applications self.skipWaiting()

Service Worker Caching Strategies

Service Workers provide fine-grained cache control capabilities. Common strategies include:

Cache-First with Network Fallback:

// sw.js
const CACHE_NAME = 'v1';

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request).then((cached) => {
      return cached || fetch(event.request).then((response) => {
        // Dynamically cache non-GET requests and opaque responses
        if (event.request.method !== 'GET' || response.status === 0) {
          return response;
        }
        
        const responseToCache = response.clone();
        caches.open(CACHE_NAME).then((cache) => {
          cache.put(event.request, responseToCache);
        });
        
        return response;
      }).catch(() => {
        // Return fallback content when the network fails
        return new Response('Offline fallback content');
      });
    })
  );
});

Pre-Caching Critical Resources:

// Pre-cache list generated during build
const PRE_CACHE_LIST = [
  '/css/main.css',
  '/js/app.js',
  '/offline.html'
];

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

Cache Update and Invalidation Mechanisms

Effective cache invalidation strategies are a key focus in engineering:

Version Number Control:

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

API Request Cache Control:

// Encapsulated fetch with caching
const apiCache = new Map();

async function cachedFetch(url, options = {}) {
  const cacheKey = `${url}_${JSON.stringify(options)}`;
  
  // Check in-memory cache
  if (apiCache.has(cacheKey)) {
    const { data, timestamp } = apiCache.get(cacheKey);
    if (Date.now() - timestamp < 300000) { // 5-minute validity
      return data;
    }
  }
  
  // Actual request
  try {
    const res = await fetch(url, options);
    const data = await res.json();
    
    // Update cache
    apiCache.set(cacheKey, {
      data,
      timestamp: Date.now()
    });
    
    return data;
  } catch (error) {
    // Return cached data if available on failure
    if (apiCache.has(cacheKey)) {
      return apiCache.get(cacheKey).data;
    }
    throw error;
  }
}

Special Scenario Handling

Form Submission Anti-Duplication Caching:

<!-- Use autocomplete control -->
<form autocomplete="off">
  <input type="text" name="key" autocomplete="new-password">
</form>

Video Segment Caching Strategy:

// MediaSource extended buffering
const mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);

mediaSource.addEventListener('sourceopen', () => {
  const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E"');
  
  fetch('/video/segment1.mp4').then(response => {
    return response.arrayBuffer();
  }).then(data => {
    sourceBuffer.appendBuffer(data);
  });
});

Monitoring and Exception Handling

Establish a cache health monitoring system:

// Cache hit rate statistics
window.addEventListener('load', () => {
  const timing = performance.getEntriesByType('navigation')[0];
  const cacheRatio = (timing.transferSize - timing.encodedBodySize) / timing.transferSize;
  analytics.send('cache_hit_ratio', cacheRatio);
});

// Cache exception monitoring
window.addEventListener('error', (e) => {
  if (e.message.includes('QuotaExceededError')) {
    metrics.increment('storage.quota_exceeded');
  }
});

Multi-Environment Differentiated Configuration

Different environments should adopt different caching strategies:

// Environment detection and strategy switching
const getCacheStrategy = () => {
  if (process.env.NODE_ENV === 'development') {
    return {
      apiCacheTTL: 0,
      staticAssets: 'no-store'
    };
  }
  
  if (location.host.includes('staging')) {
    return {
      apiCacheTTL: 300000,
      staticAssets: 'max-age=300'
    };
  }
  
  return {
    apiCacheTTL: 3600000,
    staticAssets: 'max-age=31536000'
  };
};

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

如果侵犯了你的权益请来信告知我们删除。邮箱: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 ☕.