Overview
CRXJS brings Vite’s Hot Module Replacement (HMR) to Chrome extensions, enabling instant updates during development without manual extension reloads in most cases.How HMR Works
CRXJS intercepts Vite’s HMR events and applies updates to different parts of your extension:- Extension pages (popup, options, devtools): Full HMR with framework support
- Content scripts: HMR without page reload
- Background scripts: Full extension reload
Extension Pages HMR
Extension HTML pages (popup, options, devtools) support full HMR:popup.tsx
- React/Vue component changes (with state preservation)
- CSS modifications
- TypeScript/JavaScript edits
- Asset imports
Content Script HMR
Content scripts receive HMR updates through a special port connection to the Vite dev server: From the source code (plugin-hmr.ts:60):Content Script Updates
CRXJS tracks content script dependencies and applies updates: From the source code (plugin-hmr.ts:159):- Content script code changes
- Imported module updates
- CSS modifications
- Framework component updates
HMR Timeout
Content scripts have an HMR timeout to prevent stale connections:vite.config.ts
Background Script Reloads
Changes to background scripts trigger a full extension reload because service workers control the entire extension: From the source code (plugin-hmr.ts:122):HMR Client Injection
CRXJS injects HMR clients into your extension:Service Worker Client
The background script loads an HMR client that connects to the Vite dev server:Content Script Client
Content scripts load the Vite client for HMR:Dev Server Configuration
CRXJS configures the Vite dev server for extension HMR: From the source code (plugin-hmr.ts:35):The HMR host must be
localhost for Chrome extensions. CRXJS sets this automatically.Watch Mode
CRXJS configures Vite to ignore the output directory to prevent infinite rebuild loops: From the source code (plugin-hmr.ts:51):Virtual Module HMR
CRXJS supports HMR for virtual modules (like UnoCSS, TailwindCSS): From the source code (plugin-hmr.ts:107):HMR for Frameworks
React Fast Refresh
CRXJS automatically configures React Fast Refresh for content scripts: From the source code (plugin-contentScripts.ts:88):Vue HMR
Vue components support full HMR out of the box. The@vitejs/plugin-vue handles updates automatically.
HMR Events
CRXJS sends custom HMR events:CSS HMR
CSS changes apply instantly without page reloads:- Imported CSS in content scripts
- CSS declared in manifest
content_scripts.css - CSS in extension pages
Debugging HMR
Enable HMR debug logs:HMR Limitations
MAIN World Content Scripts
Content scripts running in the MAIN world don’t support HMR:manifest.json
Manual Reload
To manually reload the extension during development:HMR Best Practices
- Separate background logic - Keep background scripts minimal to reduce reload frequency
- Use React/Vue - Framework HMR is more reliable than vanilla JS
- Test without HMR - Occasionally test with
npm run buildto catch HMR-specific issues - Save before background edits - Background changes trigger full reloads
Related
Content Scripts
Content script HMR details
Background Scripts
Why background changes reload
Pages
Extension page HMR