Fixed occasional flashes when using instant loading

This commit is contained in:
squidfunk 2023-09-30 11:33:09 +02:00
parent cef79862a2
commit 4743c1bab6
No known key found for this signature in database
GPG Key ID: 5ED40BC4F9C436DF
4 changed files with 39 additions and 10 deletions

View File

@ -250,7 +250,7 @@
</script> </script>
{% endblock %} {% endblock %}
{% block scripts %} {% block scripts %}
<script src="{{ 'assets/javascripts/bundle.726fbb30.min.js' | url }}"></script> <script src="{{ 'assets/javascripts/bundle.697ed5af.min.js' | url }}"></script>
{% for script in config.extra_javascript %} {% for script in config.extra_javascript %}
{{ script | script_tag }} {{ script | script_tag }}
{% endfor %} {% endfor %}

View File

@ -47,6 +47,7 @@ import {
import { configuration, feature } from "~/_" import { configuration, feature } from "~/_"
import { import {
Viewport, Viewport,
getElement,
getElements, getElements,
getLocation, getLocation,
getOptionalElement, getOptionalElement,
@ -82,6 +83,15 @@ interface SetupOptions {
* @returns Element map * @returns Element map
*/ */
function lookup(head: HTMLHeadElement): Map<string, HTMLElement> { function lookup(head: HTMLHeadElement): Map<string, HTMLElement> {
// @todo When resolving URLs, we must make sure to use the correct base for
// resolution. The next time we refactor instant loading, we should use the
// location subject as a source, which is also used for anchor links tracking,
// but for now we just rely on canonical.
const canonical = getElement<HTMLLinkElement>("[rel=canonical]", head)
canonical.href = canonical.href.replace("//localhost:", "//127.0.0.1")
// Create tag map and index elements in head
const tags = new Map<string, HTMLElement>() const tags = new Map<string, HTMLElement>()
for (const el of getElements(":scope > *", head)) { for (const el of getElements(":scope > *", head)) {
let html = el.outerHTML let html = el.outerHTML
@ -96,12 +106,13 @@ function lookup(head: HTMLHeadElement): Map<string, HTMLElement> {
continue continue
// Resolve URL relative to current location // Resolve URL relative to current location
const url = new URL(value, getLocation()) const url = new URL(value, canonical.href)
const ref = el.cloneNode() as HTMLElement const ref = el.cloneNode() as HTMLElement
// Set resolved URL and retrieve HTML for deduplication // Set resolved URL and retrieve HTML for deduplication
ref.setAttribute(key, `${url}`) ref.setAttribute(key, `${url}`)
html = ref.outerHTML html = ref.outerHTML
break
} }
// Index element in tag map // Index element in tag map
@ -292,6 +303,15 @@ export function setupInstantNavigation(
const source = lookup(document.head) const source = lookup(document.head)
const target = lookup(next.head) const target = lookup(next.head)
for (const [html, el] of target) { for (const [html, el] of target) {
// Hack: skip stylesheets and scripts until we manage to replace them
// entirely in order to omit flashes of white content @todo refactor
if (
el.getAttribute("rel") === "stylesheet" ||
el.hasAttribute("src")
)
continue
if (source.has(html)) { if (source.has(html)) {
source.delete(html) source.delete(html)
} else { } else {
@ -301,6 +321,15 @@ export function setupInstantNavigation(
// Remove meta tags that are not present in the new document // Remove meta tags that are not present in the new document
for (const el of source.values()) for (const el of source.values())
// Hack: skip stylesheets and scripts until we manage to replace them
// entirely in order to omit flashes of white content @todo refactor
if (
el.getAttribute("rel") === "stylesheet" ||
el.hasAttribute("src")
)
continue
else
el.remove() el.remove()
// After components and meta tags were replaced, re-evaluate scripts // After components and meta tags were replaced, re-evaluate scripts