Přidání vyhledávání na váš web pomocí JavaScriptu

Statické generátory webových stránek jako Gatsby a Jekyll jsou oblíbené, protože umožňují vytváření složitých stránek podle šablon, které lze hostovat kdekoli. Ale úžasná jednoduchost generátorů webových stránek je také omezující. Hledání je obzvlášť náročné. Jak umožníte uživatelům vyhledávat, když nemáte žádné funkce serveru ani databázi?

S JavaScriptem!

Nedávno jsme přidali vyhledávání na stránku dokumentace TrackJS, vytvořenou pomocí generátoru webových stránek Jekyll a hostovanou na stránkách GitHub. GitHub nebyl příliš nakloněn tomu, aby nám umožnil spouštět funkce vyhledávání na jejich serverech, takže jsme museli najít jiný způsob, jak spustit fulltextové vyhledávání v naší dokumentaci.

Naše dokumentace obsahuje asi 43 000 slov rozložených na 39 stránkách. To ve skutečnosti není mnoho dat, jak se ukázalo – pouze 35 kilobajtů při serializaci pro vyhledávání. To je menší než některé JavaScriptové knihovny.

Vytváření indexu vyhledávání

Našli jsme projekt s názvem Lunr.js, což je odlehčený fulltextový vyhledávač inspirovaný solr. Navíc má pouze 8,4 kilobajtů, takže jej můžeme snadno spustit na straně klienta.

Lunr používá pole klíčovaných objektů k vytvoření svého indexu, takže potřebujeme dostat naše data ke klientovi ve správném tvaru. Můžeme serializovat naše data pro vyhledávání pomocí Jekyllových nativních filtrů jako:xml_escape , strip_html a jsonify . Používáme je k sestavení objektu s dalším důležitým kontextem stránky, jako je název stránky a adresa URL. To vše se spojuje na search.html stránku.

<ol id="search-results"></ol>
<script>
    window.pages = {
        {% for page in site.pages %}
            "{{ page.url | slugify }}": {
                "title": "{{ page.title | xml_escape }}",
                "content": {{ page.content | markdownify | strip_newlines | strip_html | jsonify }},
                "url": "{{ site.url | append: page.url | xml_escape }}",
                "path": "{{ page.url | xml_escape }}"
            }{% unless forloop.last %},{% endunless %}
        {% endfor %}
    };
</script>
<script src="/lunr-2.3.5.min.js"></script>
<script src="/search.js"></script>

Výše uvedený fragment HTML je základní strukturou vyhledávací stránky. Vytváří globální proměnnou JavaScriptu pages a používá data Jekyll k sestavení hodnot ze stránek s obsahem webu.

Nyní potřebujeme indexovat data našich serializovaných stránek pomocí lunr. S naší vlastní logikou vyhledávání se budeme zabývat v samostatném search.js skript.

var searchIndex = lunr(function() {
    this.ref("id");
    this.field("title", { boost: 10 });
    this.field("content");
    for (var key in window.pages) {
        this.add({
            "id": key,
            "title": pages[key].title,
            "content": pages[key].content
        });
    }
});

Vytváříme náš nový searchIndex tím, že řekneme lunr o tvaru našich dat. Můžeme dokonce zvýšit důležitost polí při vyhledávání, jako je zvýšení důležitosti shod v názvu stránky nad obsahem stránky. Potom projdeme všechny naše globální stránky a přidáme je do indexu.

Nyní máme všechna data na stránce dokumentace ve vyhledávači lunr načteném na klientovi a připraveném k vyhledávání, kdykoli uživatel navštíví /search stránku.

Spuštění vyhledávání

Abychom mohli spustit vyhledávání, potřebujeme získat vyhledávací dotaz od uživatele. Chci, aby uživatel mohl zahájit vyhledávání odkudkoli v dokumentaci – nejen na stránce vyhledávání. Nepotřebujeme k tomu nic přepychového, můžeme použít oldschoolový HTML formulář s GET akci na stránku vyhledávání.

    <form action="/search/" method="GET">
        <input required type="search" name="q" />
        <button type="submit">Search</button>
    </form>

Když uživatel zadá vyhledávací dotaz, přenese ho na stránku vyhledávání s vyhledáváním v q Řetězec dotazu. Můžeme to vyzvednout pomocí dalšího JavaScriptu v našem search.js a spusťte vyhledávání podle našeho indexu.

function getQueryVariable(variable) {
  var query = window.location.search.substring(1);
  var vars = query.split("&");
  for (var i = 0; i < vars.length; i++) {
      var pair = vars[i].split("=");
      if (pair[0] === variable) {
          return decodeURIComponent(pair[1].replace(/\+/g, "%20"));
      }
  }
}

var searchTerm = getQueryVariable("q");
// creation of searchIndex from earlier example
var results = searchIndex.search(searchTerm);
var resultPages = results.map(function (match) {
  return pages[match.ref];
});

Výsledky, které dostáváme z lunr, nemají všechny informace, které chceme, takže výsledky mapujeme zpět na objekt původních stránek, abychom získali úplné informace o stránce Jekyll. Nyní máme pole výsledků stránek pro vyhledávání uživatele, které můžeme na stránce vykreslit.

Vykreslení výsledků

Stejně jako u jakékoli jiné úlohy vykreslování na straně klienta musíme vložit naše výsledné hodnoty do fragmentu HTML a umístit jej do DOM. Na stránce dokumentace TrackJS nepoužíváme žádný rámec pro vykreslování JavaScriptu, takže to uděláme pomocí obyčejného JavaScriptu.

// resultPages from previous example
resultsString = "";
resultPages.forEach(function (r) {
    resultsString += "<li>";
    resultsString +=   "<a class='result' href='" + r.url + "?q=" + searchTerm + "'><h3>" + r.title + "</h3></a>";
    resultsString +=   "<div class='snippet'>" + r.content.substring(0, 200) + "</div>";
    resultsString += "</li>"
});
document.querySelector("#search-results").innerHTML = resultsString;

Pokud chcete do výsledků vložit další vlastnosti stránky, například značky, musíte je přidat do serializátoru, abyste je měli v resultsPages .

S trochou zamyšlení nad designem a trochou mastnoty na loktech CSS se to ukazuje jako docela užitečné!

Jsem docela spokojený s tím, jak to dopadlo. Můžete to vidět v akci a prohlédnout si finální vyleštěný kód na stránce dokumentace TrackJS. Samozřejmě se vším tím JavaScriptem budete muset sledovat, zda tam nejsou chyby. TrackJS vám s tím může pomoci, využít bezplatnou zkušební verzi nejlepší služby pro sledování chyb, která je dnes k dispozici, a zajistit, aby váš JavaScript fungoval skvěle.

Jste připraveni na ještě lepší vyhledávání? Podívejte se na „Site Search with JavaScript Part 2“ na blogu TrackJS. Tento příklad dále rozvádíme a vylepšujeme úryvky výsledků vyhledávání tak, aby lépe zobrazovaly kontext hledaného výrazu a dynamické zvýraznění hledaného výrazu na stránkách. Opravdu to zlepšuje uživatelský zážitek.