Skip to content

Commit

Permalink
Search: Lazy load search JS on first interaction (or after 5s)
Browse files Browse the repository at this point in the history
This will reduce the QUnit homepage total uncompressed size by
~70 KB from 360KB to 290KB.
  • Loading branch information
Krinkle committed Dec 11, 2020
1 parent 53f9997 commit e3c391f
Showing 1 changed file with 42 additions and 8 deletions.
50 changes: 42 additions & 8 deletions _includes/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,38 @@
* https://www.jsdelivr.com/package/npm/algoliasearch
* https://www.jsdelivr.com/package/npm/autocomplete.js

Remember to use the 'defer' attribute.
We use type="module" as a natural way to cut the mustard,
executing the script only on modern browsers with ES6 support,
and causing no errors on older browsers.
See https://responsivenews.co.uk/post/18948466399/cutting-the-mustard
{% endcomment %}
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/algoliasearch-lite.umd.js" integrity="sha256-YuyfhK9VEyfW6ejFiPbfOX2SELbFrgFU/8tU3MHuh60=" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/autocomplete.min.js" integrity="sha256-YVWQosorZnr6fALvOW9VALYuInld27RkSPkElGBdCaU=" crossorigin="anonymous"></script>
<script type="module">
// Await deferred scripts
window.addEventListener('DOMContentLoaded', function setupSearch() {
const loadSearch = () => Promise.all([
new Promise((resolve) => document.body.append(Object.assign(document.createElement('script'), {
crossOrigin: 'anonymous',
integrity: 'sha256-YuyfhK9VEyfW6ejFiPbfOX2SELbFrgFU/8tU3MHuh60=',
src: 'https://cdn.jsdelivr.net/npm/[email protected]/dist/algoliasearch-lite.umd.js',
onload: resolve
}))),
new Promise((resolve) => document.body.append(Object.assign(document.createElement('script'), {
crossOrigin: 'anonymous',
integrity: 'sha256-YVWQosorZnr6fALvOW9VALYuInld27RkSPkElGBdCaU=',
src: 'https://cdn.jsdelivr.net/npm/[email protected]/dist/autocomplete.min.js',
onload: resolve
})))
]);
let restoreFocus = false;
async function setupSearch(e) {
// Remember if first input happened, to restore focus as-needed since
// autocomplete.js will replace the input element.
// This is before "once" check, to account for input between start and end of preload
restoreFocus = restoreFocus || (e && (e.type === 'click' || e.type === 'focus'));

// Enforce "once" for loading scripts and configuring search field
if (setupSearch.setup) return;
setupSearch.setup = 1;
await loadSearch();

const client = algoliasearch('{{ site.amethyst.algolia.application_id | default: site.algolia.application_id }}', '{{ site.amethyst.algolia.search_only_api_key }}');
{% if site.amethyst.algolia.sources -%}
const indexSources = {{ site.amethyst.algolia.sources | jsonify }};
Expand All @@ -31,8 +56,10 @@
const autocompleteOptions = {
hint: false,
ariaLabel: 'search input',
// Set debug to true if you want to inspect the dropdown
// Set debug to true to allow inspecting the dropdown
debug: true,
// Upon focus restore (see below), load suggestions if input is non-empty
openOnFocus: true,
templates: {
// https://github.com/algolia/autocomplete.js/issues/248
empty(query) {
Expand Down Expand Up @@ -77,10 +104,17 @@
}
}
}));
autocomplete('#aa-search-input', autocompleteOptions, autocompleteSources)
const $input = autocomplete('#aa-search-input', autocompleteOptions, autocompleteSources)
.on('autocomplete:selected', (e, suggestion) => location.href = suggestion._href || suggestion.url);
if (restoreFocus) $input.focus();

// Disable fallback form
document.querySelector('#site-search-form').addEventListener('submit', (e) => e.preventDefault());
});
}

// Lazyload
document.querySelector('#aa-search-input').addEventListener('focus', setupSearch, { once: true });
document.querySelector('#site-search-form').addEventListener('click', setupSearch, { once: true });
// Preload
window.addEventListener('load', () => setTimeout(setupSearch, 7000));
</script>

0 comments on commit e3c391f

Please sign in to comment.