You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(dev): hot-reload Vuetify config under SSR without a dev-server restart (#380)
* feat(dev): add supportsSsrConfigHmr capability gate
* test(e2e): prove SSR config edit currently forces a dev-server restart
* feat(dev): compute canHmrConfig capability flag on context
* feat(dev): bind config sources to virtual modules via addWatchFile
* feat(dev): collect config sources for HMR when supported, restart-watch otherwise
* feat(dev): hot-reload SSR config without dev-server restart on supported Nuxt
* fix(dev): skip nuxt.options mutations on config reload to avoid nitro reload
* test(e2e): harden config-hmr-ssr against reload-window races and pollution
* refactor(dev): unify config watch-routing in registerWatcher, drop dead builder:watch restart
* test(e2e): clear fetch-timeout timer to avoid leaked handles
* docs: SSR config changes hot-reload without dev-server restart (Nuxt >= 4.3)
* fix(dev): force SSR vite-node cache eviction so real apps hot-reload config
The previous approach (addWatchFile + handleHotUpdate reload) worked only on
tiny SSR module graphs (the e2e fixture) but not real apps: the vite-node SSR
runner never re-executed the virtual config module, so SSR served stale config.
Emit a dev-SSR-only side-effect import of the config sources from the virtual
config module so the runner records a config-file -> virtual-module dependency
edge; adding the config files to the client watcher then makes Nuxt's vite-node
invalidate set cascade through that edge to the server entry on edit. Re-read
the config and invalidate the SSR transforms inside an awaited handleHotUpdate
returning [] (no full-reload, which would suspend SSR for non-browser requests).
Verified against the real playground (SSR): theme edit reflected in ~0.7s with
no dev-server restart.
* fix(dev): broadcast full-reload on config edit so the open browser auto-refreshes
* docs+comments: document icon-set/date-adapter SSR HMR limits and test scope
Address final code review: make the icons/date SSR-eviction gap explicit (no
import edge -> not hot-reloaded under SSR, needs restart) in code comments and
the docs caveat; clarify that addWatchFile alone does not evict the SSR runner
(the dev-SSR import edge does); note the e2e guards no-restart + wiring but not
the eviction mechanism; mark the 4.3.0 floor as a conservative inference.
* feat(dev): lower SSR config-HMR floor to Nuxt 4.0.0
The required @nuxt/vite-builder internals (useInvalidates/markInvalidate/
invalidateDepTree, environments.ssr.fetchModule) and the Vite Environment API
(every Nuxt 4.x uses Vite 7) are present since 4.0.0 — verified by inspecting
the published 4.0.0-4.3.1 dists and confirmed end-to-end on apps/playground
running Nuxt 4.0.0 (config edit hot-reloaded, no dev-server restart). The 4.3.0
floor was an overly conservative untested guess. Nuxt 3 still uses the restart
fallback.
* feat(dev): lower SSR config-HMR floor to Nuxt 3.18.0
The Vite 7 + Environment-API invalidation mechanism the fix relies on landed in
@nuxt/vite-builder 3.18.0 (3.x line) and 4.0.0 (4.x line); Nuxt 3.15-3.17 ship
Vite 6 with the older mechanism and don't qualify. Confirmed end-to-end on
apps/playground at both Nuxt 3.21.8 and 4.0.0 (config edit hot-reloaded, no
restart; pre-fix build stayed stale — valid control). Nuxt 3.15-3.17 keep the
restart fallback.
* refactor: trim verbose comments to concise why-notes
* refactor: minimize comments to one-liners
* fix(dev): capture SSR module graph independent of experimental.viteEnvironmentApi
The previous code only captured the dedicated SSR dev server (flag off). With
experimental.viteEnvironmentApi enabled there's a single server and that event
never fires, so SSR config edits silently went stale. Capture the SSR graph
from server.environments.ssr in that case too. Verified on apps/playground with
the flag both off and on (config edit hot-reloaded in ~1s, no restart).
Copy file name to clipboardExpand all lines: docs/guide/configuration/vuetify-options.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,9 +7,9 @@ Support for Nuxt Layers is also available; the module scans for `vuetify.config`
7
7
During development, the module monitors Vuetify configuration files, focusing on those outside `node_modules`.
8
8
9
9
::: warning CAVEATS
10
-
Modifying the Vuetify configuration during development may trigger a full page reload (sometimes 2-3 times) to invalidate virtual modules without restarting the server. Improvements to this process are planned for future versions.
10
+
Modifying the Vuetify configuration during development triggers a full client page reload to pick up the new options — including under SSR, where the server-rendered output is refreshed without restarting the dev server (Nuxt `>= 3.18`, i.e. the Vite 7 line, and all of Nuxt 4). On Nuxt 3.15–3.17 (Vite 6), SSR falls back to a full dev-server restart.
11
11
12
-
With SSR and external configuration, the Nuxt dev server restarts due to lack of server-side HMR support in Nuxt.
12
+
Under SSR, hot-reload covers the core options — `theme`, `defaults`, `components`, `aliases`, `directives`, and locale messages. A few changes still need a manual dev-server restart to take effect: the **icon CDN / local CSS**`<head>` links (the reload intentionally skips re-applying `nuxt.options`to avoid a slower full server reload), and **icon-set / date-adapter** changes (their server-rendered modules are not re-evaluated on the fly by the dev SSR runtime).
ctx.logger.warn('`theme.defaultTheme: "system"` cannot be resolved during SSR/SSG: the server has no access to the OS color-scheme preference, so the first paint defaults to light and may flash on dark systems. Set explicit dark/light themes and enable `moduleOptions.ssrClientHints.prefersColorScheme` (optionally `prefersColorSchemeOptions.useBrowserThemeOnly`). See the SSR guide.')
99
102
}
100
103
101
-
if(ctx.icons.enabled){
104
+
if(!reload&&ctx.icons.enabled){
102
105
if(ctx.icons.local){
103
106
for(constcssofctx.icons.local){
104
107
nuxt.options.css.push(css)
@@ -119,48 +122,75 @@ export async function load (
119
122
}
120
123
}
121
124
125
+
// Returns a fn that invalidates our virtual config modules on the given graph
126
+
// (the legacy ModuleGraph or a Vite Environment's EnvironmentModuleGraph).
0 commit comments