あなたのstrapiブログに自動補完検索を加えてください


Strapi それが格納されるところに関係なく、あなたの内容を取り出すためにAPI抽象化を構築するオープンソース、ヘッドレスCMSです.それはブログや他のメディアサイトのようなコンテンツ駆動アプリケーションを構築するための素晴らしいツールです.
このポストでは、インタラクティブな検索をstrapiブログに次のように追加します.フロントエンドAlgolia 'の自動補完.JSライブラリとコミュニティは、Strapi用の検索プラグインを内蔵.

必要条件


StrapiとAlgolia AutocompleteJSはJavaScriptを使ってビルドしているので、ノードV . 12をインストールします.
あなたからの基本的なブログのアプリケーションで構築されますthis guide strapiとnextの使用.jsあなたは、そのポストの上であなたの検索経験を構築する前に、そのポストの手順を理解しなければなりません.
また、検索のためのAlgoliaアカウントが必要になります.あなたの既存のAlgoliaアカウントを使用するか、またはsign up for a free account .

裏を建てる


プロジェクトのフロントエンドとバックエンドを保持するディレクトリを作成する
mkdir blog-strapi-algolia && cd blog-strapi-algolia
StrapiはあなたがCMSを取得し、迅速に実行するために使用できるpre - bakedテンプレートのセットを持っています.これらはすべて事前に定義されたコンテンツタイプとサンプルデータを持つstrapi自体が含まれます.あなたがすでにStrapiブログを持っていないならば、あなたはすぐに一つをセットアップするためにブログテンプレートを使うことができます.
npx create-strapi-app backend  --quickstart --template @strapi/[email protected] blog
スクリプトがインストール終了後、管理ユーザを追加しますhttp://localhost:1337 それで、あなたはstrapiダッシュボードにログインできます.このスクリプトは、いくつかのデモのブログ記事を含む私たちのためのバックエンドのほとんどを設定します.で設定されたすべてについての詳細を読むことができますquick start .
次にあなたのデモコンテンツをインデックスする必要があります.幸いにも、Strapiコミュニティは、コミュニティのメンバーMattiasバン巣ベルトによって構築された検索プラグインとAlgoliaインデックス作成プロバイダで覆われています.あなたはMattieのプラグインについての詳細を読むことができますthe documentation , しかし、起きて、走ることは、2、3の構成を必要とします.
あなたがプラグインをインストールすることができるようにnpm (or yarn ).
cd backend && npm install @mattie-bundle/strapi-plugin-search @mattie-bundle/strapi-provider-search-algoliai --save
あなたは、あなたのstrapi環境にAlgolia API KeyとApp IDを加える必要があります.あなたは、設定の下でAlgoliaダッシュボードをナビゲートすることによってあなたのキーを管理することができますhttps://algolia.com/account/api-keys . StrapiはAlgoliaインデックスを変更しているので、Admin APIキー(Demos用)を提供したり、プロジェクトの適切なアクセスをするキーを作成する必要があります.
# .env
// ...
ALGOLIA_PROVIDER_APPLICATION_ID=XXXXXXXXXX
ALGOLIA_PROVIDER_ADMIN_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
適所にあなたの資格情報で、最後のステップは、プラグインを構成することです.作成または変更./config/plugins.js あなたのファイルbackend ディレクトリ.プラグインをインデックスに表示しますarticle and category ブログのコンテンツタイプ.
'use strict';

module.exports = ({ env }) => ({
  // ...
  search: {
    enabled: true,
    config: {
      provider: 'algolia',
      providerOptions: {
        apiKey: env('ALGOLIA_PROVIDER_ADMIN_API_KEY'),
        applicationId: env('ALGOLIA_PROVIDER_APPLICATION_ID'),
      },
      contentTypes: [
        { name: 'api::article.article' },
        { name: 'api::category.category' },
      ],
    },
  },
});
これらの環境変数と新しいプラグインを選択するために、strapiサーバを再起動します.npm run develop ). 新しいコンテンツがあるときに検索プラグインがトリガされますPublished , だから、どちらかにする必要がありますUnpublish and Publish デモ記事、または新しいものを作成します.strapi管理パネルをロードするhttp://localhost:1337/admin ) をクリックし、既存の記事をクリックしますUnpublish またはCreate new Entry . クリックPublish あなたのAlgoliaアプリケーションにこのエントリをインデックスにあなたの記事に.閉じるこの動画はお気に入りから削除されていますcategory あなたがそれらをインデックスにしたい場合はコンテンツタイプ.

フロントエンドの構築


あなたのバックエンドを構築し、インデックスを設定した今、あなたのためのフロントエンドを構築する時間です.
Strapiは、偉大なブログ記事を次の建物を歩いている.フロントエンド.これらのステップの上にここでビルドします.あなたはどちらかを歩くことができますquick start または、あなただけのクローンthis repo あなたが直接検索を追加するにジャンプします.
git clone --single-branch --branch no-search-version [email protected]:chuckmeyer/blog-strapi-frontend.git frontend 
走るのを忘れないようにcd frontend && npm install あなたがrepoからフロントエンドをクローン化するならば.
これは、基本的なブログサイトを稼働させるのに十分です.実行してテストすることができますnpm run devfrontend ディレクトリ.
行方不明の唯一のものは検索です.あなたは、Algolia Autocompleteを使用しています.JSライブラリは、あなたのブログのナビゲーションバーにオートコンプリート検索体験を追加します.ユーザーがフィールドに入力すると、Autocompleteは完全な用語や結果を提供することによって自分の考えを完了します.オートコンプリートライブラリは、ソースの無能なので、また、バックエンドでインデックスに接続するAlgolia InstantSearchライブラリが必要になります.
npm install @algolia/autocomplete-js algoliasearch @algolia/autocomplete-theme-classic --save
自動プロジェクトを使用して、ライブラリをラップするには自動補完コンポーネントを作成する必要があります.このためのボイラープレートを見つけることができますautocomplete documentation ../frontend/components/autocomplete.js
import { autocomplete } from '@algolia/autocomplete-js';
import React, { createElement, Fragment, useEffect, useRef } from 'react';
import { render } from 'react-dom';

export function Autocomplete(props) {
  const containerRef = useRef(null);

  useEffect(() => {
    if (!containerRef.current) {
      return undefined;
    }

    const search = autocomplete({
      container: containerRef.current,
      renderer: { createElement, Fragment },
      render({ children }, root) {
        render(children, root);
      },
      ...props,
    });

    return () => {
      search.destroy();
    };    
  }, [props]);

  return <div ref={containerRef} />;
}
バックエンドのように、APIに接続するあなたのAlgolia資格情報が必要になります.フロントエンドのみインデックスから読み取る必要があるので、アプリケーションの検索キーを使用できます.クリエイトア./frontend/.env.local あなたの資格情報を保存するファイル.
NEXT_PUBLIC_ALGOLIA_APP_ID=XXXXXXXXXX
NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
今、あなたはAlgoliaに接続を初期化することができます./frontend/components/nav.js .
import React from "react";
import Link from "next/link";

import { getAlgoliaResults } from '@algolia/autocomplete-js';
import algoliasearch from 'algoliasearch';
import { Autocomplete } from './autocomplete';
import SearchItem from './searchItem';
import "@algolia/autocomplete-theme-classic";

const searchClient = algoliasearch(
  process.env.NEXT_PUBLIC_ALGOLIA_APP_ID,
  process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY,
);

const Nav = ({ categories }) => {
  return (
    <div>
      <nav className="uk-navbar-container" data-uk-navbar>
        <div className="uk-navbar-left">
          <ul className="uk-navbar-nav">
            <li>
              <Link href="/">
                <a>Strapi Blog</a>
              </Link>
            </li>
          </ul>
        </div>
        <div className="uk-navbar-center">
          <Autocomplete
            openOnFocus={false}
            detachedMediaQuery=''
            placeholder="Search for articles"
            getSources={({ query }) => [
              {
                sourceId: "articles",
                getItemUrl( {item} ) { return `/article/${item.slug}`},
                getItems() {
                  return getAlgoliaResults({
                    searchClient,
                    queries: [
                      {
                        indexName: "development_api::article.article",
                        query,
                      }
                    ]
                  })
                },
                templates: {
                  item({ item, components}) {
                    return <SearchItem hit={item} components={components} />;
                  }
                }
              },
            ]}
          />
        </div>
        <div className="uk-navbar-right">
          <ul className="uk-navbar-nav">
            {categories.map((category) => {
              return (
                <li key={category.id}>
                  <Link href={`/category/${category.attributes.slug}`}>
                    <a className="uk-link-reset">{category.attributes.name}</a>
                  </Link>
                </li>
              );
            })}
          </ul>
        </div>
      </nav>
    </div>
  );
};

export default Nav;
ご覧の通り、いくつかのパラメータをAutocomplete コンポーネント
  • openOnFocus={false} - ユーザーが入力を開始するまでの結果を設定しないように検索を指示します
  • detachedMediaQuery='' - 別のモードで検索を開き、あなたの結果のためのより多くの部屋を提供する
  • placeholder="Search for articles" - 検索前に検索ボックスに表示されるテキスト
  • getSources={({ query }) => - あなたの自動補完体験のデータソースを定義する場所
  • 自動補完はソースの無名であることを忘れないでください.アプリケーション内のAPI、ライブラリ、または静的コンテンツに基づいてソースを定義します.ここでは、ソースと呼ばれるarticles を使用してAlgoliaインデックスにgetAlgoliaResults 関数からautocomplete-js 図書館.
                  {
                    sourceId: "articles",
                    getItemUrl( {item} ) { return `/article/${item.slug}`},
                    getItems() {
                      return getAlgoliaResults({
                        searchClient,
                        queries: [
                          {
                            indexName: "development_api::article.article",
                            query,
                          }
                        ]
                      })
                    },
                    templates: {
                      item({ item, components}) {
                        return <SearchItem hit={item} components={components} />;
                      }
                    }
                  },
    
    
    The development_api::article.article あなたのために上記のstrapi検索プラグインによって生成されたインデックスですかarticle コンテンツタイプ.あなたが生産に動くとき、プラグインは別々のものをつくりますproduction_api::article.article 同じアプリケーションのインデックス.
    The getItemUrl() セクションでは、キーボードナビゲーションを設定しますgetItems() 検索ボックスからクエリ用語を使用してインデックスから記事を取得するハンドル.
    参照の上のコードに注意してくださいSearchItem コンポーネント.これがtemplate あなたの検索結果をレンダリングするオートコンプリートを伝えるために使用します.新しいコンポーネントを追加./frontend/components/searchItem.js 次のコードを使用します.
    import React from "react";
    
    function SearchItem({ hit, components }) {
      return (
        <a className="aa-ItemLink" href={`/article/${hit.slug}`}>
          <div className="aa-ItemContent">
            <div className="ItemCategory">{hit.category.name}</div>
            <div className="aa-ItemContentBody">
              <div className="aa-ItemContentTitle">
                <components.Highlight hit={hit} attribute="title" />
              </div>
              <div className="aa-ItemContentDescription">
                <components.Highlight hit={hit} attribute="description" />
              </div>
    
            </div>
          </div>
        </a>
      );
    };
    
    export default SearchItem;
    
    このコードでは、category 記事、タイトル、および説明に関連付けられます.使用するcomponents.Highlight ユーザーのクエリにマッチする属性の一部を強調するコンポーネント.
    そしてそれで、あなたは完了です!フロントエンドサーバーを起動しますnpm run dev . 現在、ページの上部にある自動補完の検索ボックスが表示されます.それをクリックすると、検索用語を入力を開始することができますモーダル検索インターフェイスを開きます.
    このフロントエンドのホスト版を見ることができますcodesandbox , バックエンドコンテナが始まるのに少し時間がかかるかもしれません.The before and after フロントエンドコードのバージョンは両方ともgithubで利用可能です.
    このブログを使って何か冷たいものを構築するなら、私たちと共有してください.