DEV Community

Cover image for wikipedia-query: "de" iron-ajax'ified
Bryan Ollendyke
Bryan Ollendyke

Posted on

wikipedia-query: "de" iron-ajax'ified


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>` : ``}`;
  }
Enter fullscreen mode Exit fullscreen mode

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");
      }
Enter fullscreen mode Exit fullscreen mode

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);
      }
Enter fullscreen mode Exit fullscreen mode

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)