diff --git a/docs/1.getting-started/12.upgrade.md b/docs/1.getting-started/12.upgrade.md
index 642592192b..9c8f3d2bb5 100644
--- a/docs/1.getting-started/12.upgrade.md
+++ b/docs/1.getting-started/12.upgrade.md
@@ -73,7 +73,8 @@ export default defineNuxtConfig({
// resetAsyncDataToUndefined: true,
// templateUtils: true,
// relativeWatchPaths: true,
- // normalizeComponentNames: false
+ // normalizeComponentNames: false,
+ // spaLoadingTemplateLocation: 'within',
// defaults: {
// useAsyncData: {
// deep: true
@@ -237,6 +238,45 @@ export default defineNuxtConfig({
})
```
+#### New DOM Location for SPA Loading Screen
+
+🚦 **Impact Level**: Minimal
+
+##### What Changed
+
+When rendering a client-only page (with `ssr: false`), we optionally render a loading screen (from `app/spa-loading-template.html`), within the Nuxt app root:
+
+```html
+
+
+
+```
+
+Now, we default to rendering the template alongside the Nuxt app root:
+
+```html
+
+
+```
+
+##### Reasons for Change
+
+This allows the spa loading template to remain in the DOM until the Vue app suspense resolves, preventing a flash of white.
+
+##### Migration Steps
+
+If you were targeting the spa loading template with CSS or `document.queryElement` you will need to update your selectors. For this purpose you can use the new `app.spaLoaderTag` and `app.spaLoaderAttrs` configuration options.
+
+Alternatively, you can revert to the previous behaviour with:
+
+```ts twoslash [nuxt.config.ts]
+export default defineNuxtConfig({
+ experimental: {
+ spaLoadingTemplateLocation: 'within',
+ }
+})
+```
+
#### Scan Page Meta After Resolution
🚦 **Impact Level**: Minimal
diff --git a/docs/2.guide/3.going-further/1.experimental-features.md b/docs/2.guide/3.going-further/1.experimental-features.md
index 40d8c5bebf..3621f33db5 100644
--- a/docs/2.guide/3.going-further/1.experimental-features.md
+++ b/docs/2.guide/3.going-further/1.experimental-features.md
@@ -422,3 +422,24 @@ In this case, the component name would be `MyComponent`, as far as Vue is concer
But in order to auto-import it, you would need to use `SomeFolderMyComponent`.
By setting `experimental.normalizeComponentNames`, these two values match, and Vue will generate a component name that matches the Nuxt pattern for component naming.
+
+## spaLoadingTemplateLocation
+
+When rendering a client-only page (with `ssr: false`), we optionally render a loading screen (from `app/spa-loading-template.html`).
+
+It can be set to `within`, which will render it like this:
+
+```html
+
+
+
+```
+
+Alternatively, you can render the template alongside the Nuxt app root by setting it to `body`:
+
+```html
+
+
+```
+
+This avoids a white flash when hydrating a client-only page.