Files
gt-agent-company/.agents/skills/vue-best-practices/rules/hmr-vue-ssr.md
sexygoat 3c62cc1cd1 first
2026-03-31 18:41:52 +08:00

2.9 KiB

title, impact, impactDescription, type, tags
title impact impactDescription type tags
HMR Debugging for Vue SSR MEDIUM fixes Hot Module Replacement breaking in Vue SSR applications efficiency 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)

Reference