feat: vue-seo-layer, the Nuxt half of the SummerCMS SEO plugin
This commit is contained in:
39
app/middleware/seo.global.ts
Normal file
39
app/middleware/seo.global.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
// Resolves every navigation before its page runs, so a redirect or a 410
|
||||
// wins over the page (also for an old address no page matches). The
|
||||
// answer is kept in shared state for the head plugin; on hydration the
|
||||
// server's answer comes with the payload and nothing is fetched again.
|
||||
|
||||
import { seoRedirectTarget, seoResolvableUrl, seoXRobotsTag } from '../utils/seo.ts'
|
||||
|
||||
export default defineNuxtRouteMiddleware(async (to) => {
|
||||
const nuxtApp = useNuxtApp()
|
||||
const config = useRuntimeConfig()
|
||||
if ((config.public.seo as { enabled?: boolean } | undefined)?.enabled === false) return
|
||||
if (import.meta.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return
|
||||
|
||||
const state = useSeoAnswer()
|
||||
const url = seoResolvableUrl(to.fullPath)
|
||||
if (!url) {
|
||||
state.value = null
|
||||
return
|
||||
}
|
||||
const answer = await resolveSeo(url)
|
||||
state.value = answer
|
||||
if (!answer) return
|
||||
|
||||
if (import.meta.server) {
|
||||
const header = seoXRobotsTag(answer)
|
||||
if (header) useResponseHeader('X-Robots-Tag').value = header
|
||||
}
|
||||
|
||||
// On the server a redirect only sends Location (as external), so the
|
||||
// target page is not rendered and its headers stay off the redirect.
|
||||
const target = seoRedirectTarget(answer)
|
||||
if (target) {
|
||||
if (import.meta.server) useResponseHeader('X-Robots-Tag').value = undefined
|
||||
return navigateTo(target.to, { redirectCode: target.code, external: target.external || import.meta.server })
|
||||
}
|
||||
if (answer.action === 'gone') {
|
||||
return abortNavigation(createError({ statusCode: 410, statusMessage: 'Gone', fatal: true }))
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user