Julien Philippon

Mettre en place le moteur de recherche Algolia

Si vous avez un site statique et que vous souhaitez mettre en place un moteur de recherche, vous allez soit devoir créer votre API, soit utiliser une solution externe.

J’ai de nombreuses fois vu des recherches sur des sites de documentations qui utilisaient Algolia, la curiosité m’a poussé à me créer un compte et le tester. Ils proposent une solution gratuite qui permet de faire jusqu’à 10K requêtes par mois, ce qui est parfait pour commencer. Voici les étapes et quelques pistes d’optimisations qui m’ont été utiles pour l’utiliser sur ce blog.

Créez votre compte et votre premier indexe

Se créer un compte sur Algolia est très simple, vous serez guidé sur tout le processus pour faire vos premières recherches.

Générer un fichier d’import

Vous avez plusieurs façons d’envoyer des données sur leur API, le plus simple pour un site statique est de générer un json contenant l’ensemble de vos articles à indexer. Si vous utilisez Hugo, créez un fichier layouts/_default/list.algolia.json et adaptez le contenu ci-dessous en fonction de ce que vous souhaitez mettre à disposition pour la recherche.

{{ $.Scratch.Add "index" slice }}
{{ $section := $.Site.GetPage "section" .Section }}
{{ range .Site.AllPages }}
  {{ if or (and (.IsDescendant $section) (and (not .Draft) (not .Params.private))) $section.IsHome }}
    {{ $.Scratch.Add "index" (dict "objectID" .UniqueID "description" .Description "keywords" .Keywords "publishdate" .PublishDate "relpermalink" .RelPermalink "summary" .Summary "title" .Title "section" .Section "tags" .Params.Tags "categories" .Params.Categories "content" .Content) }}
  {{ end }}
{{ end }}
{{ $.Scratch.Get "index" | jsonify }}

Si tout se passe bien, vous devriez pouvoir accéder à ce fichier algolia.json.

Envoyer les données vers Algolia

J’ai utilisé le module nodejs atomic-algolia pour envoyer les données dans l’indexe. Pour l’utiliser, ajoutez les variables d’environnement suivante pour qu’elles soient accessibles au moment du build :

  • ALGOLIA_INDEX_NAME : le nom de l’index à rechercher
  • ALGOLIA_INDEX_FILE : Le fichier contenant le json, probablement ./public/algolia.json
  • ALGOLIA_ADMIN_KEY : Votre admin key que vous trouverez dans l’admin Algolia
  • ALGOLIA_APP_ID : Votre App ID que vous trouverez aussi dans l’admin Algolia

Et modifiez le script de build de cette façon :

$ hugo --minify && npm install -g atomic-algolia && atomic-algolia

Lancez un build de votre projet et l’ensemble de vos articles devraient remonter dans votre index 😎.

Intégrez le moteur de recherche sur votre site

C’est assez simple, il suffit de suivre les étapes de leur page d’installation.

Concernant le CSS, j’ai préféré le faire à ma sauce.

Petites optimisations

Surveiller les statistiques

Algolia propose des statistiques sur l’utilisation des recherche, notamment :

  • les recherches les plus fréquentes
  • Les recherches sans résultats

Ces données peuvent vous guider sur ce qu’attendent vos visiteurs du contenu de votre site 😉.

Séparez vos environnements

Pour éviter de “polluer” mes statistiques sur mes tests, j’ai créé deux indexes :

  • julien.philippon.me.production
  • julien.philippon.me.development

J’ai ensuite mis le nom de l’index dans un data-attribute, avec le dernier paramètre comprenant la variable d’environnement :

<body data-index="julien.philippon.me.{{ hugo.Environment }}">
  ...
</body>

Reste à intégrer l’index dans la configuration de instantsearch (je mets la production par défaut au cas où) :

const search = window.instantsearch({
  indexName:
    document.querySelector('body').dataset.index ||
    'julien.philippon.me.production',
  searchClient,
})

Pensez à modifier aussi la variable d’environnement ALGOLIA_INDEX_NAME.

Économisez des crédits avec un “debounce”

Par défaut, les requêtes se font à chaque touche de clavier appuyé, ce qui entraine une consommation inutile. J’aimerai que la recherche se fasse uniquement une fois que la personne a fini de taper son mot.

Dans le widget searchBox, vous pouvez ajouter un “queryHook” qui va permettre de gérer cela, en jouant avec un setTimeout :

let timerId
window.instantsearch.widgets.searchBox({
  container: '#searchbox',
  queryHook(query, refine) {
    clearTimeout(timerId)
    timerId = setTimeout(() => refine(query), 500)
  },
})

Ainsi, il faudra attendre 500 millisecondes sans qu’aucune touche ne soit actionnée avant de faire une requête.