spa-loading-template.html

The spa-loading-template.html file defines the loading screen shown while a client-side rendered page initializes.

When a page is rendered with ssr: false (either globally in nuxt.config or for specific routes with routeRules), the server returns an HTML shell without server-rendered application content. Your page content is not visible until the JavaScript bundle has been downloaded, Nuxt plugins have run, and the first page has rendered.

You can fill that gap by adding an app/spa-loading-template.html file. Its contents are inserted directly into the HTML returned by the server, so they are visible before the Nuxt client bundle has loaded.

app/spa-loading-template.html
<!-- https://github.com/barelyhuman/snips/blob/dev/pages/css-loader.md -->
<div class="loader"></div>
<style>
  .loader {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 24px;
    height: 24px;
    margin: -12px 0 0 -12px;
    border: 2px solid #efefef;
    border-top-color: #000;
    border-radius: 50%;
    animation: loader 600ms linear infinite;
  }

  @keyframes loader {
    to { transform: rotate(360deg); }
  }
</style>
This file is plain HTML that is rendered independently of Vue, so you cannot use Vue components or auto-imports in it. Include the styles needed by your loading screen directly in this file rather than relying on your application's stylesheets.
This file only covers the initial load of a client-side rendered page. To show a loading state when navigating between pages, use the <NuxtLoadingIndicator> component.

When It Is Removed

By default, the loading template is rendered next to the Nuxt app root rather than inside it:

<div id="__nuxt"></div>
<div id="__nuxt-loader"><!-- spa-loading-template.html --></div>

It stays visible until the first page is ready to render, including asynchronous setup in the page, and is then removed. This avoids a white flash between the loading screen and your page. The wrapper element can be customized with app.spaLoaderTag and app.spaLoaderAttrs; keep an id, as Nuxt uses it to remove the element.

You can render it inside the app root instead by setting the experimental spaLoadingTemplateLocation option to 'within'. In that case, it is removed as soon as Vue mounts the app, so the screen may be blank until the first page is ready to render.

Configuration

Nuxt looks for spa-loading-template.html in the app/ directory (more precisely, the dir.app directory) of your project and of each layer.

You can change this with the spaLoadingTemplate option:

  • a path (relative to srcDir, which is app/ by default) to use a different HTML file,
  • true to use Nuxt's built-in loading screen when no file is found,
  • false to disable the loading template entirely.
export default defineNuxtConfig({
  ssr: false,
  spaLoadingTemplate: 'my-loader.html',
})
Read more in Docs > Guide > Concepts > Rendering#client Side Rendering.