mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
feat(nuxt): layers support for spa loading template (#24709)
This commit is contained in:
parent
1de44a5a5c
commit
3cc333690b
@ -6,7 +6,7 @@ import { randomUUID } from 'uncrypto'
|
|||||||
import { joinURL, withTrailingSlash } from 'ufo'
|
import { joinURL, withTrailingSlash } from 'ufo'
|
||||||
import { build, copyPublicAssets, createDevServer, createNitro, prepare, prerender, scanHandlers, writeTypes } from 'nitropack'
|
import { build, copyPublicAssets, createDevServer, createNitro, prepare, prerender, scanHandlers, writeTypes } from 'nitropack'
|
||||||
import type { Nitro, NitroConfig } from 'nitropack'
|
import type { Nitro, NitroConfig } from 'nitropack'
|
||||||
import { logger, resolveIgnorePatterns, resolveNuxtModule } from '@nuxt/kit'
|
import { findPath, logger, resolveIgnorePatterns, resolveNuxtModule } from '@nuxt/kit'
|
||||||
import escapeRE from 'escape-string-regexp'
|
import escapeRE from 'escape-string-regexp'
|
||||||
import { defu } from 'defu'
|
import { defu } from 'defu'
|
||||||
import fsExtra from 'fs-extra'
|
import fsExtra from 'fs-extra'
|
||||||
@ -98,7 +98,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
baseURL: nuxt.options.app.baseURL,
|
baseURL: nuxt.options.app.baseURL,
|
||||||
virtual: {
|
virtual: {
|
||||||
'#internal/nuxt.config.mjs': () => nuxt.vfs['#build/nuxt.config'],
|
'#internal/nuxt.config.mjs': () => nuxt.vfs['#build/nuxt.config'],
|
||||||
'#spa-template': () => `export const template = ${JSON.stringify(spaLoadingTemplate(nuxt))}`
|
'#spa-template': async () => `export const template = ${JSON.stringify(await spaLoadingTemplate(nuxt))}`
|
||||||
},
|
},
|
||||||
routeRules: {
|
routeRules: {
|
||||||
'/__nuxt_error': { cache: false }
|
'/__nuxt_error': { cache: false }
|
||||||
@ -377,8 +377,9 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
const nitro = await createNitro(nitroConfig)
|
const nitro = await createNitro(nitroConfig)
|
||||||
|
|
||||||
// Trigger Nitro reload when SPA loading template changes
|
// Trigger Nitro reload when SPA loading template changes
|
||||||
|
const spaLoadingTemplateFilePath = await spaLoadingTemplatePath(nuxt)
|
||||||
nuxt.hook('builder:watch', async (_event, path) => {
|
nuxt.hook('builder:watch', async (_event, path) => {
|
||||||
if (normalize(path) === spaLoadingTemplatePath(nuxt)) {
|
if (normalize(path) === spaLoadingTemplateFilePath) {
|
||||||
await nitro.hooks.callHook('rollup:reload')
|
await nitro.hooks.callHook('rollup:reload')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -524,16 +525,20 @@ function relativeWithDot (from: string, to: string) {
|
|||||||
return relative(from, to).replace(/^([^.])/, './$1') || '.'
|
return relative(from, to).replace(/^([^.])/, './$1') || '.'
|
||||||
}
|
}
|
||||||
|
|
||||||
function spaLoadingTemplatePath (nuxt: Nuxt) {
|
async function spaLoadingTemplatePath (nuxt: Nuxt) {
|
||||||
return typeof nuxt.options.spaLoadingTemplate === 'string'
|
if (typeof nuxt.options.spaLoadingTemplate === 'string') {
|
||||||
? resolve(nuxt.options.srcDir, nuxt.options.spaLoadingTemplate)
|
return resolve(nuxt.options.srcDir, nuxt.options.spaLoadingTemplate)
|
||||||
: resolve(nuxt.options.srcDir, 'app/spa-loading-template.html')
|
}
|
||||||
|
|
||||||
|
const possiblePaths = nuxt.options._layers.map(layer => join(layer.config.srcDir, 'app/spa-loading-template.html'))
|
||||||
|
|
||||||
|
return await findPath(possiblePaths) ?? resolve(nuxt.options.srcDir, 'app/spa-loading-template.html')
|
||||||
}
|
}
|
||||||
|
|
||||||
function spaLoadingTemplate (nuxt: Nuxt) {
|
async function spaLoadingTemplate (nuxt: Nuxt) {
|
||||||
if (nuxt.options.spaLoadingTemplate === false) { return '' }
|
if (nuxt.options.spaLoadingTemplate === false) { return '' }
|
||||||
|
|
||||||
const spaLoadingTemplate = spaLoadingTemplatePath(nuxt)
|
const spaLoadingTemplate = await spaLoadingTemplatePath(nuxt)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (existsSync(spaLoadingTemplate)) {
|
if (existsSync(spaLoadingTemplate)) {
|
||||||
|
@ -181,9 +181,10 @@ export default defineUntypedSchema({
|
|||||||
/**
|
/**
|
||||||
* Boolean or a path to an HTML file with the contents of which will be inserted into any HTML page
|
* Boolean or a path to an HTML file with the contents of which will be inserted into any HTML page
|
||||||
* rendered with `ssr: false`.
|
* rendered with `ssr: false`.
|
||||||
* - If it is unset, it will use `~/app/spa-loading-template.html` if it exists.
|
* - If it is unset, it will use `~/app/spa-loading-template.html` file in one of your layers, if it exists.
|
||||||
* - If it is false, no SPA loading indicator will be loaded.
|
* - If it is false, no SPA loading indicator will be loaded.
|
||||||
* - If true, Nuxt will look for `~/app/spa-loading-template.html` file or a default Nuxt image will be used.
|
* - If true, Nuxt will look for `~/app/spa-loading-template.html` file in one of your layers, or a
|
||||||
|
* default Nuxt image will be used.
|
||||||
*
|
*
|
||||||
* Some good sources for spinners are [SpinKit](https://github.com/tobiasahlin/SpinKit) or [SVG Spinners](https://icones.js.org/collection/svg-spinners).
|
* Some good sources for spinners are [SpinKit](https://github.com/tobiasahlin/SpinKit) or [SVG Spinners](https://icones.js.org/collection/svg-spinners).
|
||||||
* @example ~/app/spa-loading-template.html
|
* @example ~/app/spa-loading-template.html
|
||||||
|
@ -64,6 +64,11 @@ describe('route rules', () => {
|
|||||||
await expectNoClientErrors('/route-rules/spa')
|
await expectNoClientErrors('/route-rules/spa')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should not render loading template in spa mode if it is not enabled', async () => {
|
||||||
|
const html = await $fetch('/route-rules/spa')
|
||||||
|
expect(html).toContain('<div id="__nuxt"></div>')
|
||||||
|
})
|
||||||
|
|
||||||
it('should allow defining route rules inline', async () => {
|
it('should allow defining route rules inline', async () => {
|
||||||
const res = await fetch('/route-rules/inline')
|
const res = await fetch('/route-rules/inline')
|
||||||
expect(res.status).toEqual(200)
|
expect(res.status).toEqual(200)
|
||||||
|
Loading…
Reference in New Issue
Block a user