title: HMR Debugging for Vue SSR impact: MEDIUM impactDescription: fixes Hot Module Replacement breaking in Vue SSR applications type: efficiency
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.
<template> changes but breaks for <script setup>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.
Step 1: Ensure correct SSR plugin configuration
import vue from '@vitejs/plugin-vue'
// vite.config.ts
import { defineConfig } from 'vite'
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()
}
HMR should work out of the box. If not:
rm -rf .nuxt node_modules/.vite
npm install
npm run dev
Ensure you're using the latest @vitejs/plugin-vue:
npm install @vitejs/plugin-vue@latest
Enable verbose HMR logging:
// vite.config.ts
export default defineConfig({
server: {
hmr: {
overlay: true
}
},
logLevel: 'info' // Shows HMR updates
})
<script> (not <script setup>) may require full reload