Это пошаговое руководство по настройке Algolia для вашего сайта Gatsby с помощью React InstantSearch.js. Сначала мы реализовали бэкэнд Algolia, а затем интерфейс. В нашем репо ключи Algolia хранятся в Секретах Github и отправляются как переменные среды через Действия Github при развертывании приложения. В этом руководстве основное внимание уделяется реализации Algolia в существующем приложении Gatsby React.
Настройка серверной части Algolia
Давайте начнем с реализации Algolia Backend.
Готовый?
Набор.
Go!
- Создайте учетную запись в Algolia и получите 4 части информации:
- Имя, которое вы дали указателю (в нашем случае "docs")
- Ваш идентификатор приложения
- Ваш ключ API только для поиска
- Ваш ключ Admin API
2. Запустите (установите dotenv, только если вы его еще не используете):
$ gatsby-plugin-algolia react-instantsearch-dom dotenv
3. Добавьте свои ключи API в файл .env.production (это просто примеры ключей. Наши фактические ключи хранятся в секретах GitHub в репозитории).
GATSBY_ALGOLIA_APP_ID = KA4OJA9KAS
GATSBY_ALGOLIA_SEARCH_KEY=lkjas987ef923ohli9asj213k12n59a
ALGOLIA_ADMIN_KEY = lksa09sadkj1230asd09dfvj12309aj
4. Добавьте следующий код в файл gatsby-config.js:
const
queries = require('./src/utils/algolia');
require('dotenv').config({ path: `.env.${process.env.NODE_ENV}`, });
module.exports = { siteMetadata: { title: 'your title', description: 'your description', author: '@gatsbyjs', siteUrl: 'https://learning.getpostman.com', // example url },
plugins: [ 'gatsby-plugin-react-helmet', { resolve: `gatsby-plugin-algolia`, options: { appId: process.env.GATSBY_ALGOLIA_APP_ID, apiKey: process.env.ALGOLIA_ADMIN_KEY, queries, chunkSize: 10000, // default: 1000 },
Примечание. Вы можете убедиться, что appID имеет красный цвет из файла .env, запустив:
$ console.log(process.env.GATSBY_ALGOLIA_APP_ID)
$ gatsby develop
Путь в gatsby-config.js должен быть:
require('dotenv').config({
path: `.env.${process.env.NODE_ENV}`,
});
4. Создайте файл в src / utils / algolia.js.
Вы можете получить данные, которые Algolia должна проиндексировать, прямо со слоя Gatsby's GraphQL. Вы можете сделать это, экспортировав массив объектов из src / utils / algolia.js. Каждый объект содержит требуемый запрос GraphQL и необязательное имя индекса, функцию преобразователя и объект настроек.
Свойство запроса: строка запроса GraphQL
Преобразователь: функция принимает данные запроса и преобразует их в массив объектов, которые станут записями индекса Algolia.
const
pageQuery = `{ docs: allMarkdownRemark( filter: { fileAbsolutePath: { regex: "/docs/"
}, } ) { edges { node { frontmatter { title contextual_links { type name url } } excerpt(pruneLength: 5000) } } } }`
const
flatten = arr => arr.map(({ node: { frontmatter, ...rest } }) => ({ ...frontmatter, ...rest, }))
const
settings = { attributesToSnippet: [`excerpt:20`] }
const
queries = [{ query: pageQuery, transformer: ({ data }) => flatten(data.docs.edges), indexName: `docs`, settings, }]
module.exports = queries
5. Gatsby development запускает сервер:
$ Run npm: build - builds the static
page
Теперь ваши "документы" индексов Algolia должны быть заполнены данными.
Советы по отладке:
- Если вы не можете получить какие-либо данные в Algolia, console.log (запросы) и проверьте, отображается ли нужная информация.
- Если это не так, запустите приложение и перейдите на localhost: 8000 / __ graphql. Вы можете скопировать и вставить сюда свой запрос graphql и проверить, какие данные возвращаются.
Интерфейс Algolia
Потрясающий! Наш бэкэнд настроен, у вас есть объекты в вашем индексе Algolia, теперь позвольте нам запустить Frontend. На полпути 👏
- Нам нужно 2 файла в src / components / Search /
- SearchPreview.jsx - содержит наш собственный код
- _search.scss - для стилизации
В searchPreview.jsx вы можете создать настраиваемый SearchBox и определить, что Hits (результаты, возвращаемые из Algolia) отображаются только тогда, когда пользователь вводит текст в SearchBox. В противном случае Algolia по умолчанию будет отображать все проиндексированные результаты при загрузке страницы. Вот как выглядит код:
import
React from 'react'; import
{ connectSearchBox, connectHits } from 'react-instantsearch-dom'; import
'./_search.scss';
const
SearchBox = ({ currentRefinement, refine }) => ( <div className="ais-SearchBox"> <form noValidate action=""
role="search"
className="ais-SearchBox-form"> <input className="ais-SearchBox-input" type="search" value={currentRefinement} onChange={(event) => refine(event.currentTarget.value)} /> </form> </div> );
export const
CustomSearchBox = connectSearchBox(SearchBox);
// print out first and last characters around search term const
getSnippet = (excerpt, match) => { const
index = excerpt.indexOf(match); return
excerpt.substring(index - 50, index + 50); };
// only display Hits when user types in SearchBox const
Hits = ({ hits }) => (
<ul className="style"> {hits.map((hit) => ( <li key={hit.title}> <a href={hit.fields.slug}> {hit.title} <p>{`...${getSnippet(hit.excerpt, hit._highlightResult.title.matchedWords[0])}...`} </p> </a> </li> ))} </ul> );
export const
CustomHits = connectHits(Hits);
Затем мы включили Algolia SearchBox в наш файл src / components / Header / Header.jsx, потому что нам нужна панель поиска по центру панели навигации Bootstrap4.
Все, что нам нужно для Algolia Frontend
- Импортируйте из Алголии все, что нам нужно
import
algoliasearch from 'algoliasearch/lite';
import
{ InstantSearch, SearchBox, Hits, Configure } from 'react-instantsearch-dom';
import
{ CustomHits } from '../Search/searchPreview';
2. Устанавливаем состояние, что поле searchInput пусто
constructor(props) {
super(props);
this.state = {
isToggledOn: false,
hasInput: false,
refresh: false,
};
}
3. Мы импортируем виджет InstantSearch и передаем наш ключ API и AppID через searchClient.
Примечание.
В Algolia есть несколько функций InstantSearches для различных библиотек и фреймворков. Мы используем React InstantSearch. В зависимости от того, какой InstantSearch вы используете, вам доступны разные варианты для разных виджетов. Вначале мне это было непонятно.
В нашем виджете React InstantSearch я настроил InstantSearch для отображения максимум 5 результатов поиска:
const
searchClient = algoliasearch('4A5N71XH', 'bf5cf4783437b12c2dca33724c9c04');
<InstantSearch searchClient={searchClient} indexName="docs" refresh={refresh} > <Configure hitsPerPage={5} /> </InstantSearch>
4. Теперь мы включаем собственно SearchBox. На данный момент React InstantSearch не имеет возможности удалить кнопки отправки / сброса по умолчанию, поэтому мы скрываем их с помощью CSS. Затем мы определяем событие onKeyUp, которое устанавливает состояние hasInput, когда пользователь начинает вводить текст в SearchBox.
<InstantSearch searchClient={searchClient} indexName="docs" refresh={refresh} > <Configure hitsPerPage={5} />
<SearchBox className="searchbox" class="ais-SearchBox-input" submit={<></>} reset={<></>} translations={{ placeholder: 'Search Postman Docs', }}
onKeyUp={(event) => { this.setState({ hasInput: event.currentTarget.value !== '', }); }} /> </InstantSearch>
5. Затем мы включили наш виджет CustomHits, который принимает хиты, возвращаемые из Algolia, которые мы определяем в нашем файле searchPreview.jsx.
Показывать результаты только тогда, когда пользователь начинает печатать
Мы оборачиваем виджет CustomHits в div, который принимает текущий setState как className, потому что виджет CustomHits не принимает имена классов изначально, и мы хотим отображать Hits только тогда, когда пользователь вводит текст в SearchBox.
<SearchBox className="searchbox" class="ais-SearchBox-input" submit={<></>} reset={<></>} translations={{ placeholder: 'Search Postman Docs', }}
onKeyUp={(event) => { this.setState({ hasInput: event.currentTarget.value !== '', }); }} />
{/*forcefeed className because component does not accept natively as prop*/}
<div className={!hasInput ? 'input-empty'
: 'input-value'}> <CustomHits hitComponent={Hits} /> </div> </InstantSearch>
6. Затем мы заключаем наш InstantSearch в ClickOutHandler, чтобы закрыть контейнер обращений, когда пользователь щелкает мышью вне SearchResults.
const
ClickOutHandler = require('react-onclickout');
onClickOut = () => { document.getElementsByClassName('ais-SearchBox-input')[0].value = ''; this.setState(() => ({ hasInput: false, })); }
<ClickOutHandler onClickOut={this.onClickOut}>
<InstantSearch searchClient={searchClient} indexName="docs" refresh={refresh} > ...
</InstantSearch> </ClickOutHandler>
7. Наконец, мы стилизуем наш Sarchbox и Hits. Вы можете стилизовать их, добавив classNames или сославшись на classNames Algolia и добавив наш собственный стиль, перезаписав стиль по умолчанию. Вот как выглядит наш CSS для SearchBox:
.searchbox {
input { background-color:#f5f5f5; border: 0; padding: 13px 24px; border-radius: 3px; width: 100%; }
::placeholder { color: #1c272b; font-size: 14px; font-weight: 600; }
.ais-SearchBox-submit, .ais-SearchBox-reset { display: none; } }
8. Последнее, что нужно включить, это, конечно, поддержку IE11 для Aloglia в наш файл seo.jsx. Передаем сценарий в шлеме Гэтсби.
<Helmet> {/* Algolia IE11 support */}
<script src="https://polyfill.io/v3/polyfill.min.js?features=default,Array.prototype.find,Array.prototype.includes"
/> </Helmet>
И готово!
Поздравляю! Теперь вы настроили Algolia React InstantSearch в своем приложении Gatsby React. Вот наша реализация Algolia в Учебном центре Postman.
Дайте мне знать, что вы думаете, или, если у вас есть вопросы, напишите мне в Twitter 👩💻 Мне нравится читать / твитить / ретвитнуть все виды технического / кодового контента 🏄♀️