Loading...
Loading...
Implement caching strategies for HTTP, service workers, and memoization
npx skill4agent add manastalukdar/claude-devstudio cache-strategy$ARGUMENTS# Check for existing cache configurations
echo "=== Cache Configuration Audit ==="
# Check for service worker
if [ -f "public/service-worker.js" ] || [ -f "src/service-worker.js" ] || [ -f "sw.js" ]; then
echo "✓ Service Worker detected"
ls -lh **/service-worker.js **/sw.js 2>/dev/null | head -5
else
echo "✗ No Service Worker found"
fi
# Check for HTTP caching headers (common web server configs)
if [ -f ".htaccess" ]; then
echo "✓ Apache .htaccess found"
grep -i "cache-control\|expires" .htaccess 2>/dev/null | head -5
fi
if [ -f "nginx.conf" ] || [ -f "nginx/*.conf" ]; then
echo "✓ Nginx config found"
grep -i "cache\|expires" nginx*.conf 2>/dev/null | head -5
fi
# Check for Redis/Memcached dependencies
if grep -q "\"redis\"" package.json 2>/dev/null; then
echo "✓ Redis client installed"
fi
if grep -q "\"memcached\"" package.json 2>/dev/null; then
echo "✓ Memcached client installed"
fi
# Check for caching libraries
if grep -q "\"workbox\"" package.json 2>/dev/null; then
echo "✓ Workbox (service worker toolkit) installed"
fi
# Check CDN configuration
if [ -f "vercel.json" ] || [ -f "netlify.toml" ]; then
echo "✓ CDN configuration detected"
fi// Static assets with long-term caching
app.use('/static', express.static('public', {
maxAge: '1y',
immutable: true,
etag: true
}));
// API responses with short-term caching
app.use('/api', (req, res, next) => {
res.set('Cache-Control', 'private, max-age=300'); // 5 minutes
next();
});// next.config.js
module.exports = {
async headers() {
return [
{
source: '/_next/static/:path*',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable',
},
],
},
];
},
};# Static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# HTML files - no cache
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate";
}import { precacheAndRoute } from 'workbox-precaching';
import { registerRoute } from 'workbox-routing';
import { CacheFirst, NetworkFirst, StaleWhileRevalidate } from 'workbox-strategies';
import { ExpirationPlugin } from 'workbox-expiration';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
// Precache static assets
precacheAndRoute(self.__WB_MANIFEST);
// Cache images with Cache First strategy
registerRoute(
({ request }) => request.destination === 'image',
new CacheFirst({
cacheName: 'images',
plugins: [
new ExpirationPlugin({
maxEntries: 60,
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
}),
],
})
);
// API calls with Network First strategy
registerRoute(
({ url }) => url.pathname.startsWith('/api/'),
new NetworkFirst({
cacheName: 'api-cache',
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
}),
new ExpirationPlugin({
maxAgeSeconds: 5 * 60, // 5 minutes
}),
],
})
);
// CSS and JS with Stale While Revalidate
registerRoute(
({ request }) => request.destination === 'style' || request.destination === 'script',
new StaleWhileRevalidate({
cacheName: 'static-resources',
})
);import { useMemo, useCallback } from 'react';
import { memo } from 'react';
// Memoize expensive calculations
const ExpensiveComponent = ({ data }) => {
const processedData = useMemo(() => {
return expensiveCalculation(data);
}, [data]);
const handleClick = useCallback(() => {
// Handler logic
}, []);
return <div>{processedData}</div>;
};
export default memo(ExpensiveComponent);// Simple memoization utility
function memoize(fn) {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn(...args);
cache.set(key, result);
return result;
};
}
// LRU cache with size limit
class LRUCache {
constructor(limit = 100) {
this.cache = new Map();
this.limit = limit;
}
get(key) {
if (!this.cache.has(key)) return undefined;
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value); // Move to end
return value;
}
set(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key);
} else if (this.cache.size >= this.limit) {
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, value);
}
}const redis = require('redis');
const client = redis.createClient();
// Cache middleware
const cache = (duration) => {
return async (req, res, next) => {
const key = `cache:${req.originalUrl}`;
try {
const cached = await client.get(key);
if (cached) {
return res.json(JSON.parse(cached));
}
// Store original send function
const originalSend = res.json.bind(res);
// Override send to cache response
res.json = (body) => {
client.setex(key, duration, JSON.stringify(body));
return originalSend(body);
};
next();
} catch (err) {
next();
}
};
};
// Use cache middleware
app.get('/api/data', cache(300), async (req, res) => {
const data = await fetchData();
res.json(data);
});.claude/cache/cache-strategy/cache_patterns.json{
"redis": {
"express": "// Express Redis middleware...",
"nextjs": "// Next.js Redis client...",
"django": "# Django Redis cache backend..."
},
"service_worker": {
"workbox": "// Workbox config...",
"vanilla": "// Vanilla SW..."
},
"http_headers": {
"nginx": "location ~* ...",
"apache": "ExpiresActive On...",
"express": "app.use(express.static..."
},
"in_memory": {
"react": "useMemo hook...",
"node": "LRU cache class...",
"python": "functools.lru_cache..."
}
}# Identify cache targets (100 tokens vs. 2,000 reading all code)
grep -r "fetch\|axios\|api\." src/ --files-with-matches
grep -r "SELECT\|query\|find\(" src/ --files-with-matches
grep -r "expensive\|calculation\|compute" src/ --files-with-matches.claude/cache/cache-strategy/hot_paths.json{
"api_routes": ["src/api/users.js", "src/api/products.js"],
"db_queries": ["src/models/User.js"],
"expensive_calculations": ["src/utils/analytics.js"],
"last_scan": "2026-01-27T10:00:00Z"
}.claude/cache/cache-strategy/recommendations.json{
"ttl_guidelines": {
"static_assets": "1y (31536000s)",
"api_responses": "5m (300s)",
"user_data": "no-cache",
"computed_data": "1h (3600s)"
},
"invalidation_patterns": {
"time_based": "Use max-age + stale-while-revalidate",
"event_based": "Cache tags + manual clear",
"version_based": "Content hashing for assets"
},
"cache_strategies": {
"cache_first": "Static assets, images, fonts",
"network_first": "API calls, real-time data",
"stale_while_revalidate": "Semi-dynamic content"
}
}.claude/cache/cache-strategy/framework_templates.json{
"express_redis": {
"middleware": "const cache = (duration) => {...}",
"client_setup": "const redis = require('redis')...",
"error_handling": "try { cached = await client.get... }"
},
"nextjs_swr": {
"config": "export const fetcher = ...",
"revalidation": "revalidateOnFocus: false..."
},
"django_redis": {
"settings": "CACHES = { 'default': {...} }",
"decorator": "@cache_page(60 * 15)..."
}
}.claude/cache/cache-strategy/implementation_status.json{
"src/api/users.js": {
"status": "redis_cache_added",
"ttl": 300,
"last_modified": "2026-01-27T10:00:00Z"
},
"src/components/ExpensiveChart.js": {
"status": "memoization_added",
"technique": "useMemo",
"last_modified": "2026-01-27T09:00:00Z"
},
"public/service-worker.js": {
"status": "workbox_configured",
"strategies": ["CacheFirst", "NetworkFirst"],
"last_modified": "2026-01-26T15:00:00Z"
}
}# Fast detection (5 commands vs. reading all configs)
ls -la public/service-worker.js 2>/dev/null
grep -q "redis\|memcached" package.json
ls -la nginx.conf .htaccess 2>/dev/null
grep -q "workbox\|sw-precache" package.json
ls -la vercel.json netlify.toml 2>/dev/nullhttpredisservice-worker# Load cached template, insert into file
# No generation, no examples, direct application# Clear stale cache (e.g., after major refactor)
rm -rf .claude/cache/cache-strategy/{
"triggers_webpack_optimize": ["Build tool cache needed"],
"triggers_performance_profile": ["Measure cache hit rates"],
"triggers_lighthouse": ["Validate cache headers"],
"triggered_by_ci_setup": ["CI/CD cache configuration"]
}/webpack-optimize/performance-profile/lighthouse/ci-setup/webpack-optimize/performance-profile# Clear browser cache for testing
# Chrome DevTools: Application > Clear storage
# Clear Redis cache
redis-cli FLUSHDB
# Clear service worker cache
# Chrome DevTools: Application > Service Workers > Unregister# Restore previous configuration
git checkout HEAD -- nginx.conf service-worker.js
# Clear problematic cache
# Rebuild and redeploy