From 42807fcdf91bcdd54ef1ed4edd21b46e4c26f417 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 5 Jan 2018 01:40:52 +0330 Subject: [PATCH] perf: Use getPreloadFiles for HTTP2 push headers --- lib/common/options.js | 3 ++- lib/core/middleware/nuxt.js | 31 +++++++++++++++++++++---------- lib/core/renderer.js | 10 ++++------ 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/lib/common/options.js b/lib/common/options.js index 3f8fe27a0..af70751c3 100755 --- a/lib/common/options.js +++ b/lib/common/options.js @@ -267,7 +267,8 @@ Options.defaults = { resourceHints: true, ssr: undefined, http2: { - push: false + push: false, + shouldPush: null }, static: {}, gzip: { diff --git a/lib/core/middleware/nuxt.js b/lib/core/middleware/nuxt.js index a0c0f0d41..9905b2f8c 100644 --- a/lib/core/middleware/nuxt.js +++ b/lib/core/middleware/nuxt.js @@ -11,7 +11,7 @@ module.exports = async function nuxtMiddleware(req, res, next) { try { const result = await this.renderRoute(req.url, context) await this.nuxt.callHook('render:route', req.url, result) - const { html, error, redirected, resourceHints } = result + const { html, error, redirected, getPreloadFiles } = result if (redirected) { return html @@ -31,21 +31,32 @@ module.exports = async function nuxtMiddleware(req, res, next) { res.setHeader('ETag', etag) } - // HTTP2 push headers + // HTTP2 push headers for preload assets if (!error && this.options.render.http2.push) { // 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}`) + const preloadFiles = getPreloadFiles() + const { shouldPush } = this.options.render.http2 + const { publicPath } = this.resources.clientManifest + + preloadFiles.forEach(({ file, asType, fileWithoutQuery, extension }) => { + // By default, we only preload scripts or css + if (!shouldPush && asType !== 'script' && asType !== 'style') { + return } - } + + // User wants to explicitly control what to preload + if (shouldPush && !shouldPush(fileWithoutQuery, asType)) { + return + } + + pushAssets.push(`<${publicPath}${file}>; rel=preload; as=${asType}`) + }) + // Pass with single Link header - // https://blog.cloudflare.com/http-2-server-push-with-multiple-assets-per-link-header + // https://preloadFilesblog.cloudflare.com/http-2-server-push-with-multiple-assets-per-link-header + // https://www.w3.org/Protocols/9707-link-header.html res.setHeader('Link', pushAssets.join(',')) } diff --git a/lib/core/renderer.js b/lib/core/renderer.js index 57e8d79fd..eff0ed19c 100644 --- a/lib/core/renderer.js +++ b/lib/core/renderer.js @@ -312,12 +312,10 @@ module.exports = class Renderer { HEAD += `` } - let resourceHints = '' - - if (this.options.render.resourceHints) { - resourceHints = context.renderResourceHints() - HEAD += resourceHints + if (this.options.render.preloadLinks) { + HEAD += context.renderResourceHints() } + APP += `` APP += context.renderScripts() APP += m.script.text({ body: true }) @@ -334,7 +332,7 @@ module.exports = class Renderer { return { html, - resourceHints, + getPreloadFiles: context.getPreloadFiles, error: context.nuxt.error, redirected: context.redirected }