diff --git a/lib/render.js b/lib/render.js index f4e3af8fce..d389c92ec9 100644 --- a/lib/render.js +++ b/lib/render.js @@ -54,13 +54,14 @@ export async function render (req, res) { res.statusCode = 404 return res.end() } - const { html, error, redirected } = await this.renderRoute(req.url, context) + const { html, error, redirected, resourceHints } = await this.renderRoute(req.url, context) if (redirected) { return html } if (error) { res.statusCode = context.nuxt.error.statusCode || 500 } + // ETag header if (!error && this.options.render.etag) { const etag = generateETag(html, this.options.render.etag) if (fresh(req.headers, { etag })) { @@ -72,6 +73,18 @@ export async function render (req, res) { } res.setHeader('Content-Type', 'text/html; charset=utf-8') res.setHeader('Content-Length', Buffer.byteLength(html)) + // Parse resourceHints to extract HTTP.2 prefetch/push headers + // https://w3c.github.io/preload/#server-push-http-2 + const regex = /link rel="([^"]*)" href="([^"]*)" as="([^"]*)"/g + const pushAssets = [] + let m + while (m = regex.exec(resourceHints)) { // eslint-disable-line no-cond-assign + const [_, rel, href, as] = m + if (rel === 'preload') { + pushAssets.push(`<${href}>; rel=${rel}; as=${as}`) + } + } + res.setHeader('Link', pushAssets) res.end(html, 'utf8') return html } catch (err) { @@ -106,7 +119,8 @@ export async function renderRoute (url, context = {}) { if (this._routerBaseSpecified) { HEAD += `` } - HEAD += context.renderResourceHints() + context.renderStyles() + const resourceHints = context.renderResourceHints() + HEAD += resourceHints + context.renderStyles() APP += `` APP += context.renderScripts() const html = this.appTemplate({ @@ -117,6 +131,7 @@ export async function renderRoute (url, context = {}) { }) return { html, + resourceHints, error: context.nuxt.error, redirected: context.redirected }