Chrome Extension Performance Optimization — Developer Guide
3 min readPerformance Optimization for Chrome Extensions
Introduction
- Extensions share browser resources — slow extensions degrade the whole browser
- MV3 service workers add startup latency — optimize for cold starts
- Key metrics: startup time, memory usage, message latency, content script injection time
Service Worker Performance
- Cold start: SW loads from disk on every wake-up — keep bundle small
- Tree-shake unused code, use dynamic
import()for optional features - Register all event listeners synchronously at top level (Chrome requirement)
- Avoid heavy initialization — defer work until needed ```javascript // BAD: heavy work at startup const data = await fetch(“https://api.example.com/config”); // blocks SW init
// GOOD: defer until needed let cachedConfig; async function getConfig() { if (!cachedConfig) cachedConfig = await fetch(“https://api.example.com/config”); return cachedConfig; }
## Bundle Size Optimization {#bundle-size-optimization}
- Use Webpack/Vite/Rollup with tree-shaking enabled
- Analyze bundle: `webpack-bundle-analyzer` or `rollup-plugin-visualizer`
- Code split: dynamic `import()` for features not needed at startup
- Minify production builds (but don't obfuscate — CWS rejects obfuscated code)
- Target: background bundle < 100KB, content scripts < 50KB
## Storage Performance {#storage-performance}
- `chrome.storage` is async and involves IPC — minimize calls
- Use `@theluckystrike/webext-storage` batch operations:
```typescript
// BAD: 5 separate storage calls
const a = await storage.get('a');
const b = await storage.get('b');
// GOOD: single call
const { a, b } = await storage.getMany(['a', 'b']);
// GOOD: get everything at once for settings pages
const all = await storage.getAll();
setManyfor batch writes — single IPC call instead of multiple- Cache frequently read values in memory, use
watch()to stay in sync
Content Script Performance
run_at: "document_idle"(default) — least impact on page loadrun_at: "document_start"— blocks page rendering, use only when essential- Minimize DOM queries — cache element references
- Use
MutationObserverinstead of polling for DOM changes - Avoid injecting large CSS files — use minimal, scoped styles
Message Passing Performance
- Each message involves serialization + IPC — don’t send huge payloads
- Batch small messages into single larger message
- Use
@theluckystrike/webext-messagingtyped messages — compile-time checks prevent unnecessary round-trips - For streaming data, consider
chrome.runtime.connect()(long-lived port) instead of one-shot messages
Memory Management
- Service worker memory is reclaimed on termination — design for this
- Content scripts live with the page — avoid memory leaks:
- Remove event listeners when done
- Clear intervals/timeouts
- Don’t hold references to detached DOM nodes
- Use
WeakRef/WeakMapfor caches that should be GC’d - Monitor:
chrome://extensionsshows per-extension memory usage
Popup/Options Performance
- Popups load fresh every time — optimize initial render
- Pre-compute data in background, send to popup via messaging
- Use
@theluckystrike/webext-storagegetAll()for initial state load - Lazy-load heavy UI components
Network Performance
- Cache API responses in
chrome.storage.local - Use
If-Modified-Since/ETagfor conditional requests - Batch API calls where possible
- Use
chrome.alarmsfor periodic sync instead of continuous polling
Profiling Tools
- Chrome DevTools Performance tab — works for extension pages
chrome://extensions— memory and CPU usage per extensionperformance.now()for measuring code execution timeconsole.time()/console.timeEnd()for quick timingchrome.runtime.getBackgroundClient()for SW inspection
Performance Checklist
- Background bundle < 100KB
- Content script bundle < 50KB
- Batch storage reads (
getMany/getAll) - Batch storage writes (
setMany) - Event listeners registered synchronously
- Heavy work deferred (not at SW startup)
- Content script uses
document_idle - No memory leaks in content scripts
- API responses cached
- No unnecessary message passing
Related Articles
Related Articles
Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.