Increase perceived performance by scrolling to the right spot before Hydrogen loads (#128)
This commit is contained in:
parent
3671da0405
commit
fa4720af04
|
@ -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',
|
||||
`
|
||||
<script type="text/javascript" nonce="${renderOptions.pageOptions.cspNonce}">
|
||||
window.matrixPublicArchiveContext = ${safeJson(serializedContext)}
|
||||
</script>
|
||||
`
|
||||
);
|
||||
|
||||
const vmRenderScriptFilePath = renderOptions.vmRenderScriptFilePath;
|
||||
const hydrogenRenderScriptCode = await readFile(vmRenderScriptFilePath, 'utf8');
|
||||
|
|
|
@ -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(
|
|||
</head>
|
||||
<body>
|
||||
${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.
|
||||
*/ ''
|
||||
}
|
||||
<script type="text/javascript" nonce="${pageOptions.cspNonce}">
|
||||
const qs = new URLSearchParams(window?.location?.search);
|
||||
const atEventId = qs.get('at');
|
||||
if (atEventId) {
|
||||
const el = document.querySelector(\`[data-event-id="\${atEventId}"]\`);
|
||||
requestAnimationFrame(() => {
|
||||
el && el.scrollIntoView({ block: 'center' });
|
||||
});
|
||||
} else {
|
||||
const el = document.querySelector('.js-bottom-scroll-anchor');
|
||||
requestAnimationFrame(() => {
|
||||
el && el.scrollIntoView({ block: 'end' });
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" nonce="${pageOptions.cspNonce}">
|
||||
window.matrixPublicArchiveContext = ${safeJson(serializedMatrixPublicArchiveContext)}
|
||||
</script>
|
||||
|
||||
${pageOptions.scripts
|
||||
.map(
|
||||
(scriptUrl) =>
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
[
|
||||
|
|
Loading…
Reference in New Issue