Skip to content
This repository was archived by the owner on Apr 6, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions packages/nuxt/src/app/nuxt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import type { RuntimeConfig } from '@nuxt/schema'
import { getContext } from 'unctx'
import type { SSRContext } from 'vue-bundle-renderer/runtime'
import type { CompatibilityEvent } from 'h3'
// eslint-disable-next-line import/no-restricted-paths
import type { NuxtRenderContext } from '../core/runtime/nitro/renderer'

const nuxtAppCtx = getContext<NuxtApp>('nuxt-app')

Expand All @@ -21,11 +19,13 @@ type NuxtMeta = {
}

type HookResult = Promise<void> | void

type AppRenderedContext = { ssrContext: NuxtApp['ssrContext'] }
export interface RuntimeNuxtHooks {
'app:created': (app: App<Element>) => HookResult
'app:beforeMount': (app: App<Element>) => HookResult
'app:mounted': (app: App<Element>) => HookResult
'app:rendered': (ctx: NuxtRenderContext) => HookResult
'app:rendered': (ctx: AppRenderedContext) => HookResult
'app:redirected': () => HookResult
'app:suspense:resolve': (Component?: VNode) => HookResult
'app:error': (err: any) => HookResult
Expand Down
70 changes: 32 additions & 38 deletions packages/nuxt/src/core/runtime/nitro/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,13 @@ export type NuxtSSRContext = NuxtApp['ssrContext']

const defineRenderHandler = _defineRenderHandler as (h: RenderHandler) => CompatibilityEvent

export interface NuxtRenderContext {
ssrContext: NuxtSSRContext
html: {
htmlAttrs: string[]
head: string[]
bodyAttrs: string[]
bodyPreprend: string[]
body: string[]
bodyAppend: string[]
}
export interface NuxtRenderHTMLContext {
htmlAttrs: string[]
head: string[]
bodyAttrs: string[]
bodyPreprend: string[]
body: string[]
bodyAppend: string[]
}

export interface NuxtRenderResponse {
Expand Down Expand Up @@ -124,6 +121,7 @@ export default defineRenderHandler(async (event) => {
const _rendered = await renderer.renderToString(ssrContext).catch((err) => {
if (!ssrError) { throw err }
})
await ssrContext.nuxt?.hooks.callHook('app:rendered', { ssrContext })

// Handle errors
if (!_rendered) {
Expand All @@ -137,42 +135,38 @@ export default defineRenderHandler(async (event) => {
const renderedMeta = await ssrContext.renderMeta?.() ?? {}

// Create render context
const rendered: NuxtRenderContext = {
ssrContext,
html: {
htmlAttrs: normalizeChunks([renderedMeta.htmlAttrs]),
head: normalizeChunks([
renderedMeta.headTags,
_rendered.renderResourceHints(),
_rendered.renderStyles(),
ssrContext.styles
]),
bodyAttrs: normalizeChunks([renderedMeta.bodyAttrs]),
bodyPreprend: normalizeChunks([
renderedMeta.bodyScriptsPrepend,
ssrContext.teleports?.body
]),
body: [
const htmlContext: NuxtRenderHTMLContext = {
htmlAttrs: normalizeChunks([renderedMeta.htmlAttrs]),
head: normalizeChunks([
renderedMeta.headTags,
_rendered.renderResourceHints(),
_rendered.renderStyles(),
ssrContext.styles
]),
bodyAttrs: normalizeChunks([renderedMeta.bodyAttrs]),
bodyPreprend: normalizeChunks([
renderedMeta.bodyScriptsPrepend,
ssrContext.teleports?.body
]),
body: [
// TODO: Rename to _rendered.body in next vue-bundle-renderer
_rendered.html
],
bodyAppend: normalizeChunks([
_rendered.html
],
bodyAppend: normalizeChunks([
`<script>window.__NUXT__=${devalue(ssrContext.payload)}</script>`,
_rendered.renderScripts(),
// Note: bodyScripts may contain tags other than <script>
renderedMeta.bodyScripts
])
}
])
}

// Allow hooking into the rendered result
const nitroApp = useNitroApp()
await ssrContext.nuxt?.hooks.callHook('app:rendered', rendered)
await nitroApp.hooks.callHook('nuxt:app:rendered', rendered)
await nitroApp.hooks.callHook('render:html', htmlContext, { event })

// Construct HTML response
const response: RenderResponse = {
body: renderHTMLDocument(rendered),
body: renderHTMLDocument(htmlContext),
statusCode: event.res.statusCode,
statusMessage: event.res.statusMessage,
headers: {
Expand Down Expand Up @@ -206,10 +200,10 @@ function joinAttrs (chunks: string[]) {
return chunks.join(' ')
}

function renderHTMLDocument (rendered: NuxtRenderContext) {
function renderHTMLDocument (html: NuxtRenderHTMLContext) {
return `<!DOCTYPE html>
<html ${joinAttrs(rendered.html.htmlAttrs)}>
<head>${joinTags(rendered.html.head)}</head>
<body ${joinAttrs(rendered.html.bodyAttrs)}>${joinTags(rendered.html.bodyPreprend)}${joinTags(rendered.html.body)}${joinTags(rendered.html.bodyAppend)}</body>
<html ${joinAttrs(html.htmlAttrs)}>
<head>${joinTags(html.head)}</head>
<body ${joinAttrs(html.bodyAttrs)}>${joinTags(html.bodyPreprend)}${joinTags(html.body)}${joinTags(html.bodyAppend)}</body>
</html>`
}