hmr-vue-ssr.md
2.89 KB
title: HMR Debugging for Vue SSR
impact: MEDIUM
impactDescription: fixes Hot Module Replacement breaking in Vue SSR applications
type: efficiency
tags: vite, hmr, ssr, vue, hot-reload, server-side-rendering
HMR Debugging for Vue SSR
Impact: MEDIUM - fixes Hot Module Replacement breaking in Vue SSR applications
Hot Module Replacement breaks when modifying Vue component <script setup> sections in SSR applications. Changes cause errors instead of smooth updates, requiring full page reloads.
Symptoms
- HMR works for
<template>changes but breaks for<script setup> - "Cannot read property of undefined" after saving
- Full page reload required after script changes
- HMR works in dev:client but not dev:ssr
Root Cause
SSR mode has a different transformation pipeline. The Vue plugin's HMR boundary detection doesn't handle SSR modules the same way as client modules.
Fix
Step 1: Ensure correct SSR plugin configuration
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
ssr: {
// Don't externalize these for HMR to work
noExternal: ['vue', '@vue/runtime-core', '@vue/runtime-dom']
}
})
Step 2: Configure dev server for SSR HMR
// server.ts
import { createServer } from 'vite'
const vite = await createServer({
server: { middlewareMode: true },
appType: 'custom'
})
// Use vite.ssrLoadModule for server-side imports
const { render } = await vite.ssrLoadModule('/src/entry-server.ts')
// Handle HMR
vite.watcher.on('change', async (file) => {
if (file.endsWith('.vue')) {
// Invalidate the module
const mod = vite.moduleGraph.getModuleById(file)
if (mod) {
vite.moduleGraph.invalidateModule(mod)
}
}
})
Step 3: Add HMR acceptance in entry-server
// entry-server.ts
import { createApp } from './main'
export async function render(url: string) {
const app = createApp()
// ... render logic
}
// Accept HMR updates
if (import.meta.hot) {
import.meta.hot.accept()
}
Framework-Specific Solutions
Nuxt 3
HMR should work out of the box. If not:
rm -rf .nuxt node_modules/.vite
npm install
npm run dev
Vite SSR Template
Ensure you're using the latest @vitejs/plugin-vue:
npm install @vitejs/plugin-vue@latest
Debugging
Enable verbose HMR logging:
// vite.config.ts
export default defineConfig({
server: {
hmr: {
overlay: true
}
},
logLevel: 'info' // Shows HMR updates
})
Known Limitations
- HMR for
<script>(not<script setup>) may require full reload - SSR components with external dependencies may not hot-reload
- State is not preserved for SSR components (expected behavior)