manage: speed up first meaningful paint

by postponing creation of favicon placeholders for the visible entries to the second render run when rendering in chunks or after all styles were displayed when rendering the entire list
This commit is contained in:
tophf 2017-12-26 08:52:19 +03:00
parent 8c5ad8fe4b
commit 4da6eeb746

View File

@ -118,6 +118,7 @@ function showStyles(styles = []) {
return info; return info;
}); });
let index = 0; let index = 0;
let firstRun = true;
installed.dataset.total = styles.length; installed.dataset.total = styles.length;
const scrollY = (history.state || {}).scrollY; const scrollY = (history.state || {}).scrollY;
const shouldRenderAll = scrollY > window.innerHeight || sessionStorage.justEditedStyleId; const shouldRenderAll = scrollY > window.innerHeight || sessionStorage.justEditedStyleId;
@ -139,13 +140,15 @@ function showStyles(styles = []) {
renderBin.appendChild(createStyleElement(sorted[index++])); renderBin.appendChild(createStyleElement(sorted[index++]));
} }
filterAndAppend({container: renderBin}); filterAndAppend({container: renderBin});
if (newUI.enabled && newUI.favicons) {
debounce(handleEvent.loadFavicons);
}
if (index < sorted.length) { if (index < sorted.length) {
requestAnimationFrame(renderStyles); requestAnimationFrame(renderStyles);
if (firstRun) setTimeout(recreateStyleTargets, 0, {styles, iconsOnly: true});
firstRun = false;
return; return;
} }
if (newUI.enabled && newUI.favicons) {
setTimeout(recreateStyleTargets, 0, {iconsOnly: true});
}
if ('scrollY' in (history.state || {}) && !sessionStorage.justEditedStyleId) { if ('scrollY' in (history.state || {}) && !sessionStorage.justEditedStyleId) {
setTimeout(window.scrollTo, 0, 0, history.state.scrollY); setTimeout(window.scrollTo, 0, 0, history.state.scrollY);
} }
@ -154,7 +157,7 @@ function showStyles(styles = []) {
delete sessionStorage.justEditedStyleId; delete sessionStorage.justEditedStyleId;
if (entry) { if (entry) {
animateElement(entry); animateElement(entry);
scrollElementIntoView(entry); requestAnimationFrame(() => scrollElementIntoView(entry));
} }
} }
} }
@ -218,9 +221,10 @@ function createStyleElement({style, name, index}) {
} }
function createStyleTargetsElement({entry, style}) { function createStyleTargetsElement({entry, style, iconsOnly}) {
const parts = createStyleElement.parts; const parts = createStyleElement.parts;
const targets = parts.targets.cloneNode(true); const entryTargets = $('.targets', entry);
const targets = iconsOnly ? entryTargets : parts.targets.cloneNode(true);
let container = targets; let container = targets;
let numTargets = 0; let numTargets = 0;
const displayed = new Set(); const displayed = new Set();
@ -231,14 +235,14 @@ function createStyleTargetsElement({entry, style}) {
continue; continue;
} }
displayed.add(targetValue); displayed.add(targetValue);
const element = template.appliesToTarget.cloneNode(true); const element = iconsOnly ? targets.children[numTargets] : template.appliesToTarget.cloneNode(true);
if (!newUI.enabled) { if (!newUI.enabled) {
if (numTargets === 10) { if (numTargets === 10) {
container = container.appendChild(template.extraAppliesTo.cloneNode(true)); container = container.appendChild(template.extraAppliesTo.cloneNode(true));
} else if (numTargets > 1) { } else if (numTargets > 1) {
container.appendChild(template.appliesToSeparator.cloneNode(true)); container.appendChild(template.appliesToSeparator.cloneNode(true));
} }
} else if (newUI.favicons) { } else if (newUI.favicons && entry.parentElement) {
let favicon = ''; let favicon = '';
if (type === 'domains') { if (type === 'domains') {
favicon = GET_FAVICON_URL + targetValue; favicon = GET_FAVICON_URL + targetValue;
@ -249,15 +253,24 @@ function createStyleTargetsElement({entry, style}) {
favicon = favicon ? GET_FAVICON_URL + favicon[1] : ''; favicon = favicon ? GET_FAVICON_URL + favicon[1] : '';
} }
if (favicon) { if (favicon) {
element.appendChild(document.createElement('img')).dataset.src = favicon; const img = element.children[0];
if (!img || img.localName !== 'img') {
element.insertAdjacentElement('afterbegin', document.createElement('img'))
.dataset.src = favicon;
} else if ((img.dataset.src || img.src) !== favicon) {
img.src = '';
img.dataset.src = favicon;
}
} }
} }
element.appendChild( if (!iconsOnly) {
document.createTextNode( element.appendChild(
(parts.decorations[type + 'Before'] || '') + document.createTextNode(
targetValue + (parts.decorations[type + 'Before'] || '') +
(parts.decorations[type + 'After'] || ''))); targetValue +
container.appendChild(element); (parts.decorations[type + 'After'] || '')));
container.appendChild(element);
}
numTargets++; numTargets++;
} }
} }
@ -267,9 +280,8 @@ function createStyleTargetsElement({entry, style}) {
$('.applies-to', entry).classList.add('has-more'); $('.applies-to', entry).classList.add('has-more');
} }
} }
const entryTargets = $('.targets', entry);
if (numTargets) { if (numTargets) {
entryTargets.parentElement.replaceChild(targets, entryTargets); if (!iconsOnly) entryTargets.parentElement.replaceChild(targets, entryTargets);
} else { } else {
entryTargets.appendChild(template.appliesToEverything.cloneNode(true)); entryTargets.appendChild(template.appliesToEverything.cloneNode(true));
} }
@ -277,6 +289,23 @@ function createStyleTargetsElement({entry, style}) {
} }
function recreateStyleTargets({styles, iconsOnly = false} = {}) {
Promise.resolve(styles || getStylesSafe()).then(styles => {
for (const style of styles) {
const entry = $(ENTRY_ID_PREFIX + style.id);
if (entry) {
createStyleTargetsElement({
entry,
style,
iconsOnly,
});
}
}
debounce(handleEvent.loadFavicons);
});
}
Object.assign(handleEvent, { Object.assign(handleEvent, {
ENTRY_ROUTES: { ENTRY_ROUTES: {
@ -559,15 +588,7 @@ function switchUI({styleOnly} = {}) {
return; return;
} }
if (missingFavicons) { if (missingFavicons) {
getStylesSafe().then(styles => { recreateStyleTargets();
for (const style of styles) {
const entry = $(ENTRY_ID_PREFIX + style.id);
if (entry) {
createStyleTargetsElement({entry, style});
}
}
debounce(handleEvent.loadFavicons);
});
return; return;
} }
} }