From fa4720af04b568ef022256940b05c55a55d0383b Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Wed, 9 Nov 2022 18:57:33 -0600 Subject: [PATCH] Increase perceived performance by scrolling to the right spot before Hydrogen loads (#128) --- .../render-hydrogen-to-string-unsafe.js | 34 ++++++++++++------- ...-hydrogen-vm-render-script-to-page-html.js | 34 +++++++++++++++++++ server/routes/room-directory-routes.js | 1 + server/routes/room-routes.js | 1 + .../JumpToNextActivitySummaryTileView.js | 7 +++- 5 files changed, 64 insertions(+), 13 deletions(-) diff --git a/server/hydrogen-render/render-hydrogen-to-string-unsafe.js b/server/hydrogen-render/render-hydrogen-to-string-unsafe.js index 6895d4e..980a2bd 100644 --- a/server/hydrogen-render/render-hydrogen-to-string-unsafe.js +++ b/server/hydrogen-render/render-hydrogen-to-string-unsafe.js @@ -16,9 +16,7 @@ const vm = require('vm'); const path = require('path'); const { readFile } = require('fs').promises; const crypto = require('crypto'); - const { parseHTML } = require('linkedom'); -const safeJson = require('../lib/safe-json'); // Setup the DOM context with any necessary shims/polyfills and ensure the VM // context global has everything that a normal document does so Hydrogen can @@ -67,24 +65,36 @@ async function _renderHydrogenToStringUnsafe(renderOptions) { assert(renderOptions.vmRenderScriptFilePath); assert(renderOptions.vmRenderContext); assert(renderOptions.pageOptions); + assert(renderOptions.pageOptions.locationHref); assert(renderOptions.pageOptions.cspNonce); const { dom, vmContext } = createDomAndSetupVmContext(); + // A small `window.location` stub + if (!dom.window.location) { + const locationUrl = new URL(renderOptions.pageOptions.locationHref); + dom.window.location = {}; + [ + 'hash', + 'host', + 'hostname', + 'href', + 'origin', + 'password', + 'pathname', + 'port', + 'protocol', + 'search', + 'username', + ].forEach((key) => { + dom.window.location[key] = locationUrl[key]; + }); + } + // Define this for the SSR context dom.window.matrixPublicArchiveContext = { ...renderOptions.vmRenderContext, }; - // Serialize it for when we run this again client-side - const serializedContext = JSON.stringify(dom.window.matrixPublicArchiveContext); - dom.document.body.insertAdjacentHTML( - 'beforeend', - ` - - ` - ); const vmRenderScriptFilePath = renderOptions.vmRenderScriptFilePath; const hydrogenRenderScriptCode = await readFile(vmRenderScriptFilePath, 'utf8'); diff --git a/server/hydrogen-render/render-hydrogen-vm-render-script-to-page-html.js b/server/hydrogen-render/render-hydrogen-vm-render-script-to-page-html.js index 56b8de2..380d804 100644 --- a/server/hydrogen-render/render-hydrogen-vm-render-script-to-page-html.js +++ b/server/hydrogen-render/render-hydrogen-vm-render-script-to-page-html.js @@ -26,6 +26,12 @@ async function renderHydrogenVmRenderScriptToPageHtml( pageOptions, }); + // Serialize the state for when we run the Hydrogen render again client-side to + // re-hydrate the DOM + const serializedMatrixPublicArchiveContext = JSON.stringify({ + ...vmRenderContext, + }); + const serializableSpans = getSerializableSpans(); const serializedSpans = JSON.stringify(serializableSpans); @@ -51,6 +57,34 @@ async function renderHydrogenVmRenderScriptToPageHtml( ${hydrogenHtmlOutput} + + ${ + /** + * This inline snippet is used in to scroll the Hydrogen timeline to the + * right place immediately when the page loads instead of waiting for + * Hydrogen to load, hydrate and finally scroll. + */ '' + } + + + + ${pageOptions.scripts .map( (scriptUrl) => diff --git a/server/routes/room-directory-routes.js b/server/routes/room-directory-routes.js index 2be031f..f07b784 100644 --- a/server/routes/room-directory-routes.js +++ b/server/routes/room-directory-routes.js @@ -93,6 +93,7 @@ router.get( title: `Matrix Public Archive`, styles: [hydrogenStylesUrl, stylesUrl, roomDirectoryStylesUrl], scripts: [jsBundleUrl], + locationHref: urlJoin(basePath, req.originalUrl), shouldIndex, cspNonce: res.locals.cspNonce, } diff --git a/server/routes/room-routes.js b/server/routes/room-routes.js index 1f19b92..7e909ab 100644 --- a/server/routes/room-routes.js +++ b/server/routes/room-routes.js @@ -420,6 +420,7 @@ router.get( title: `${roomData.name} - Matrix Public Archive`, styles: [hydrogenStylesUrl, stylesUrl], scripts: [jsBundleUrl], + locationHref: urlJoin(basePath, req.originalUrl), shouldIndex, cspNonce: res.locals.cspNonce, } diff --git a/shared/views/JumpToNextActivitySummaryTileView.js b/shared/views/JumpToNextActivitySummaryTileView.js index 8517416..238eff5 100644 --- a/shared/views/JumpToNextActivitySummaryTileView.js +++ b/shared/views/JumpToNextActivitySummaryTileView.js @@ -23,7 +23,12 @@ class JumpToNextActivitySummaryTileView extends TemplateView { return t.div( { - className: 'JumpToNextActivitySummaryTileView', + className: { + JumpToNextActivitySummaryTileView: true, + // Used by page loaded JavaScript to quickly jump the scroll viewport down + // while we wait for the rest of the JavaScript to load. + 'js-bottom-scroll-anchor': true, + }, 'data-event-id': vm.eventId, }, [