From f2ca0a9377e73fb636ad70159487f4b531bc8683 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 28 Sep 2022 12:27:26 +0100 Subject: [PATCH 1/3] perf(nitro): respond with early hints in node-based environments --- packages/nuxt/src/core/runtime/nitro/renderer.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/nuxt/src/core/runtime/nitro/renderer.ts b/packages/nuxt/src/core/runtime/nitro/renderer.ts index fcb56a73f75..40e3efdb185 100644 --- a/packages/nuxt/src/core/runtime/nitro/renderer.ts +++ b/packages/nuxt/src/core/runtime/nitro/renderer.ts @@ -148,6 +148,12 @@ export default defineRenderHandler(async (event) => { ssrContext.payload.prerenderedAt = Date.now() } + if (!isRenderingPayload && !process.env.prerender && event.res.socket) { + const { link } = await getEarlyHints() + // TODO: use https://github.com/nodejs/node/pull/44180 when we drop support for node 16 + event.res.socket!.write(`HTTP/1.1 103 Early Hints\r\nLink: ${link}\r\n\r\n`, 'utf-8',) + } + // Render app const renderer = (process.env.NUXT_NO_SSR || ssrContext.noSSR) ? await getSPARenderer() : await getSSRRenderer() const _rendered = await renderer.renderToString(ssrContext).catch((err) => { @@ -303,3 +309,11 @@ function splitPayload (ssrContext: NuxtSSRContext) { payload: { data, prerenderedAt } } } + +const getEarlyHints = lazyCachedFunction(async () => { + const renderer = process.env.NUXT_NO_SSR ? await getSPARenderer() : await getSSRRenderer() + const result = await renderer.renderToString({ + runtimeConfig: useRuntimeConfig() as NuxtSSRContext['runtimeConfig'], + } as any) + return result.renderResourceHeaders() +}) From dc2e983826b212c54630fa51795c794a4183476d Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 28 Sep 2022 13:11:53 +0100 Subject: [PATCH 2/3] perf: remove extra render cycle on first request --- .../nuxt/src/core/runtime/nitro/renderer.ts | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/packages/nuxt/src/core/runtime/nitro/renderer.ts b/packages/nuxt/src/core/runtime/nitro/renderer.ts index 40e3efdb185..2e2eb8a046c 100644 --- a/packages/nuxt/src/core/runtime/nitro/renderer.ts +++ b/packages/nuxt/src/core/runtime/nitro/renderer.ts @@ -1,4 +1,4 @@ -import { createRenderer } from 'vue-bundle-renderer/runtime' +import { createRenderer, renderResourceHeaders } from 'vue-bundle-renderer/runtime' import type { RenderResponse } from 'nitropack' import type { Manifest } from 'vite' import { appendHeader, getQuery } from 'h3' @@ -100,7 +100,10 @@ const getSPARenderer = lazyCachedFunction(async () => { return Promise.resolve(result) } - return { renderToString } + return { + rendererContext: renderer.rendererContext, + renderToString + } }) const PAYLOAD_CACHE = (process.env.NUXT_PAYLOAD_EXTRACTION && process.env.prerender) ? new Map() : null // TODO: Use LRU cache @@ -148,14 +151,16 @@ export default defineRenderHandler(async (event) => { ssrContext.payload.prerenderedAt = Date.now() } + // Render app + const renderer = (process.env.NUXT_NO_SSR || ssrContext.noSSR) ? await getSPARenderer() : await getSSRRenderer() + + // Render 103 Early Hints if (!isRenderingPayload && !process.env.prerender && event.res.socket) { - const { link } = await getEarlyHints() + const { link } = renderResourceHeaders({}, renderer.rendererContext) // TODO: use https://github.com/nodejs/node/pull/44180 when we drop support for node 16 event.res.socket!.write(`HTTP/1.1 103 Early Hints\r\nLink: ${link}\r\n\r\n`, 'utf-8',) } - // Render app - const renderer = (process.env.NUXT_NO_SSR || ssrContext.noSSR) ? await getSPARenderer() : await getSSRRenderer() const _rendered = await renderer.renderToString(ssrContext).catch((err) => { if (!ssrError) { // Use explicitly thrown error in preference to subsequent rendering errors @@ -309,11 +314,3 @@ function splitPayload (ssrContext: NuxtSSRContext) { payload: { data, prerenderedAt } } } - -const getEarlyHints = lazyCachedFunction(async () => { - const renderer = process.env.NUXT_NO_SSR ? await getSPARenderer() : await getSSRRenderer() - const result = await renderer.renderToString({ - runtimeConfig: useRuntimeConfig() as NuxtSSRContext['runtimeConfig'], - } as any) - return result.renderResourceHeaders() -}) From 55ff9ddafe120e98f91ffda654725dab9ee45152 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 28 Sep 2022 13:16:31 +0100 Subject: [PATCH 3/3] style: remove trailing comma --- packages/nuxt/src/core/runtime/nitro/renderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt/src/core/runtime/nitro/renderer.ts b/packages/nuxt/src/core/runtime/nitro/renderer.ts index 2e2eb8a046c..828aec1a84f 100644 --- a/packages/nuxt/src/core/runtime/nitro/renderer.ts +++ b/packages/nuxt/src/core/runtime/nitro/renderer.ts @@ -158,7 +158,7 @@ export default defineRenderHandler(async (event) => { if (!isRenderingPayload && !process.env.prerender && event.res.socket) { const { link } = renderResourceHeaders({}, renderer.rendererContext) // TODO: use https://github.com/nodejs/node/pull/44180 when we drop support for node 16 - event.res.socket!.write(`HTTP/1.1 103 Early Hints\r\nLink: ${link}\r\n\r\n`, 'utf-8',) + event.res.socket!.write(`HTTP/1.1 103 Early Hints\r\nLink: ${link}\r\n\r\n`, 'utf-8') } const _rendered = await renderer.renderToString(ssrContext).catch((err) => {