This video shows how we got off of iron-ajax and replaced it with fetch
+ IntersectionObserverMixin to give us a performance optimized method of ONLY querying wikipedia when the user can see the element. Text explaining what's in the video follows.
What's a "mix-in"?
A "mix-in" isn't a real thing but it's a methodology developers usually use to reference a JS development technique called SuperClass
. SuperClass allows us to "mix" aspects of one object into another. So we start with one class based object and then we "mix-in" certain pieces of functionality, usually tying into hooks / life-cycle aspects of the underlying class.
What IntersectionObserverMixin provides
- Automatically creates an IntersectionObserver
- When the element is 25% visible, it sets a property called
elementVisible
- Then it removes the listener for intersection for performance
This gives us the ability to automatically set a stateful property based on the thing being visible, where "thing" is literally any web component!
How wikipedia-query leverages this capability
Full code for wikipedia-query web component
// LitElement render function
render() {
return html`
${this.elementVisible ? html`
<h3 .hidden="${this.hideTitle}">${this._title}</h3>
<div id="result"></div>
<citation-element
creator="{Wikipedia contributors}"
scope="sibling"
license="by-sa"
title="${this.search} --- {Wikipedia}{,} The Free Encyclopedia"
source="https://en.wikipedia.org/w/index.php?title=${this.search}"
date="${this.__now}"
></citation-element>` : ``}`;
}
The render
function (a LitElement convention to update the shadowRoot of our element) ONLY shows content IF we are currently visible! This keeps the DOM from having to present information until it's actually visible to the user's screen.
We also only request the element citation-element
when we are visible as seen below.
/**
* LitElement properties updated
*/
updated(changedProperties) {
changedProperties.forEach((oldValue, propName) => {
// element is visible, now we can search
if (propName == "elementVisible" && this[propName]) {
import("@lrnwebcomponents/citation-element/citation-element.js");
}
LitElement generates change records when properties are updated. Then we see if we are visible and if we are (meaning we were not hence change, and then true to be visible) we use import()
which is a dynamic import for another element! HTML will automatically "hydrate" or populate the definition of the citation-element
in the shadowRoot above. This means that we show the code for our element AND we only import the definitions of code in our element IF the element is currently on screen!
Last, let's go get that yummy wikipedia data
updateArticle(search) {
fetch(
`https://en.wikipedia.org/w/api.php?origin=*&action=query&titles=${search}&prop=extracts&format=json`
)
.then((response) => {
if (response.ok) return response.json();
})
.then((json) => {
this.handleResponse(json);
});
}
/**
* LitElement properties updated
*/
updated(changedProperties) {
changedProperties.forEach((oldValue, propName) => {
// element is visible, now we can search
if (propName == "elementVisible" && this[propName]) {
import("@lrnwebcomponents/citation-element/citation-element.js");
}
if (
["elementVisible", "search"].includes(propName) &&
this.search &&
this.elementVisible
) {
clearTimeout(this._debounce);
this._debounce = setTimeout(() => {
this.updateArticle(this.search);
}, 25);
}
We use fetch
to replace iron-ajax
but we don't just do that. We ONLY search for data if the element has something to search for AND it is currently visible. This gives us an ultra performant way of shipping a wikipedia-query tag across all browsers and platforms while only requesting data when the user has need for it.
Top comments (0)