Add preload link headers for downstream Cloudflare early hints (#171)
Because it takes us at best several seconds to request information from a homeserver and then server-side render the page, the browser has to wait for the response before it can even try loading the necessary assets. With this change that facilitates early hints, the browser can preload all of the assets necessary before we are done generating the response and will be ready to go by the time we're all done on the server. Fix https://github.com/matrix-org/matrix-public-archive/issues/32 Part of https://github.com/matrix-org/matrix-public-archive/issues/132 See https://developers.cloudflare.com/cache/about/early-hints/ for information on enabling in Cloudflare
This commit is contained in:
parent
321c6a4f26
commit
17a39ab8db
|
@ -0,0 +1,29 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
// Set some preload link headers which we can use with Cloudflare to turn into 103 early
|
||||||
|
// hints, https://developers.cloudflare.com/cache/about/early-hints/
|
||||||
|
//
|
||||||
|
// This will turn into a nice speed-up since the server side render can take some time
|
||||||
|
// while we fetch all the information from the homeserver and the page can have all of
|
||||||
|
// the assets loaded and ready to go by that time. This way there is no extra delay
|
||||||
|
// after the page gets served.
|
||||||
|
function setHeadersToPreloadAssets(res, pageOptions) {
|
||||||
|
assert(res);
|
||||||
|
assert(pageOptions);
|
||||||
|
|
||||||
|
const { styles, scripts } = pageOptions;
|
||||||
|
|
||||||
|
const styleLinks = styles.map((styleUrl) => {
|
||||||
|
return `<${styleUrl}>; rel=preload; as=style`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const scriptLinks = scripts.map((scriptUrl) => {
|
||||||
|
return `<${scriptUrl}>; rel=preload; as=script`;
|
||||||
|
});
|
||||||
|
|
||||||
|
res.append('Link', [].concat(styleLinks, scriptLinks).join(', '));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = setHeadersToPreloadAssets;
|
|
@ -8,6 +8,7 @@ const asyncHandler = require('../lib/express-async-handler');
|
||||||
|
|
||||||
const fetchPublicRooms = require('../lib/matrix-utils/fetch-public-rooms');
|
const fetchPublicRooms = require('../lib/matrix-utils/fetch-public-rooms');
|
||||||
const renderHydrogenVmRenderScriptToPageHtml = require('../hydrogen-render/render-hydrogen-vm-render-script-to-page-html');
|
const renderHydrogenVmRenderScriptToPageHtml = require('../hydrogen-render/render-hydrogen-vm-render-script-to-page-html');
|
||||||
|
const setHeadersToPreloadAssets = require('../lib/set-headers-to-preload-assets');
|
||||||
|
|
||||||
const config = require('../lib/config');
|
const config = require('../lib/config');
|
||||||
const basePath = config.get('basePath');
|
const basePath = config.get('basePath');
|
||||||
|
@ -65,15 +66,16 @@ router.get(
|
||||||
const roomDirectoryStylesUrl = urlJoin(basePath, '/css/room-directory.css');
|
const roomDirectoryStylesUrl = urlJoin(basePath, '/css/room-directory.css');
|
||||||
const jsBundleUrl = urlJoin(basePath, '/js/entry-client-room-directory.es.js');
|
const jsBundleUrl = urlJoin(basePath, '/js/entry-client-room-directory.es.js');
|
||||||
|
|
||||||
|
const pageOptions = {
|
||||||
|
title: `Matrix Public Archive`,
|
||||||
|
styles: [hydrogenStylesUrl, stylesUrl, roomDirectoryStylesUrl],
|
||||||
|
scripts: [jsBundleUrl],
|
||||||
|
locationHref: urlJoin(basePath, req.originalUrl),
|
||||||
|
shouldIndex,
|
||||||
|
cspNonce: res.locals.cspNonce,
|
||||||
|
};
|
||||||
const pageHtml = await renderHydrogenVmRenderScriptToPageHtml({
|
const pageHtml = await renderHydrogenVmRenderScriptToPageHtml({
|
||||||
pageOptions: {
|
pageOptions,
|
||||||
title: `Matrix Public Archive`,
|
|
||||||
styles: [hydrogenStylesUrl, stylesUrl, roomDirectoryStylesUrl],
|
|
||||||
scripts: [jsBundleUrl],
|
|
||||||
locationHref: urlJoin(basePath, req.originalUrl),
|
|
||||||
shouldIndex,
|
|
||||||
cspNonce: res.locals.cspNonce,
|
|
||||||
},
|
|
||||||
vmRenderScriptFilePath: path.resolve(
|
vmRenderScriptFilePath: path.resolve(
|
||||||
__dirname,
|
__dirname,
|
||||||
'../../shared/room-directory-vm-render-script.js'
|
'../../shared/room-directory-vm-render-script.js'
|
||||||
|
@ -102,6 +104,8 @@ router.get(
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setHeadersToPreloadAssets(res, pageOptions);
|
||||||
|
|
||||||
res.set('Content-Type', 'text/html');
|
res.set('Content-Type', 'text/html');
|
||||||
res.send(pageHtml);
|
res.send(pageHtml);
|
||||||
})
|
})
|
||||||
|
|
|
@ -23,6 +23,7 @@ const timestampToEvent = require('../lib/matrix-utils/timestamp-to-event');
|
||||||
const { removeMe_fetchRoomCreateEventId } = require('../lib/matrix-utils/fetch-room-data');
|
const { removeMe_fetchRoomCreateEventId } = require('../lib/matrix-utils/fetch-room-data');
|
||||||
const getMessagesResponseFromEventId = require('../lib/matrix-utils/get-messages-response-from-event-id');
|
const getMessagesResponseFromEventId = require('../lib/matrix-utils/get-messages-response-from-event-id');
|
||||||
const renderHydrogenVmRenderScriptToPageHtml = require('../hydrogen-render/render-hydrogen-vm-render-script-to-page-html');
|
const renderHydrogenVmRenderScriptToPageHtml = require('../hydrogen-render/render-hydrogen-vm-render-script-to-page-html');
|
||||||
|
const setHeadersToPreloadAssets = require('../lib/set-headers-to-preload-assets');
|
||||||
const MatrixPublicArchiveURLCreator = require('matrix-public-archive-shared/lib/url-creator');
|
const MatrixPublicArchiveURLCreator = require('matrix-public-archive-shared/lib/url-creator');
|
||||||
const {
|
const {
|
||||||
MS_LOOKUP,
|
MS_LOOKUP,
|
||||||
|
@ -868,15 +869,16 @@ router.get(
|
||||||
const stylesUrl = urlJoin(basePath, '/css/styles.css');
|
const stylesUrl = urlJoin(basePath, '/css/styles.css');
|
||||||
const jsBundleUrl = urlJoin(basePath, '/js/entry-client-hydrogen.es.js');
|
const jsBundleUrl = urlJoin(basePath, '/js/entry-client-hydrogen.es.js');
|
||||||
|
|
||||||
|
const pageOptions = {
|
||||||
|
title: `${roomData.name} - Matrix Public Archive`,
|
||||||
|
styles: [hydrogenStylesUrl, stylesUrl],
|
||||||
|
scripts: [jsBundleUrl],
|
||||||
|
locationHref: urlJoin(basePath, req.originalUrl),
|
||||||
|
shouldIndex,
|
||||||
|
cspNonce: res.locals.cspNonce,
|
||||||
|
};
|
||||||
const pageHtml = await renderHydrogenVmRenderScriptToPageHtml({
|
const pageHtml = await renderHydrogenVmRenderScriptToPageHtml({
|
||||||
pageOptions: {
|
pageOptions,
|
||||||
title: `${roomData.name} - Matrix Public Archive`,
|
|
||||||
styles: [hydrogenStylesUrl, stylesUrl],
|
|
||||||
scripts: [jsBundleUrl],
|
|
||||||
locationHref: urlJoin(basePath, req.originalUrl),
|
|
||||||
shouldIndex,
|
|
||||||
cspNonce: res.locals.cspNonce,
|
|
||||||
},
|
|
||||||
vmRenderScriptFilePath: path.resolve(__dirname, '../../shared/hydrogen-vm-render-script.js'),
|
vmRenderScriptFilePath: path.resolve(__dirname, '../../shared/hydrogen-vm-render-script.js'),
|
||||||
vmRenderContext: {
|
vmRenderContext: {
|
||||||
toTimestamp,
|
toTimestamp,
|
||||||
|
@ -900,6 +902,8 @@ router.get(
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setHeadersToPreloadAssets(res, pageOptions);
|
||||||
|
|
||||||
res.set('Content-Type', 'text/html');
|
res.set('Content-Type', 'text/html');
|
||||||
res.send(pageHtml);
|
res.send(pageHtml);
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue