ライブデモ
サーバー側の Algolia インデックス更新用のユーティリティと、Svelte アプリ用のクライアント側の検索コンポーネント。単一の依存関係のみを追加します。
algoliasearch
algoliasearch/lite
(13 KB)。 svelte-algolia
設定するには 3 つの手順があります。
npm install --dev svelte-algolia
algoliaConfig
オブジェクトを作成します。
import 'dotenv/config' // optional
async function loadPokedex ( ) {
const json = await import ( 'pokedex.json' )
return json . default . map ( ( el ) => ( { ... el , id : el . someUniqAttribute } ) )
}
const algoliaConfig = {
appId : process . env . VITE_ALGOLIA_APP_ID ,
// don't prefix admin key with VITE_ else it would get exposed to client-side code
apiKey : process . env . ALGOLIA_ADMIN_KEY ,
indices : [
{ name : `Pokedex` , getData : loadPokedex } ,
{ name : `Hitchhiker's Guide` , getData : guideLoader } ,
] ,
settings : {
attributesToHighlight : [ `name` ] ,
} ,
}
getData
関数は、インデックスを付けたいデータ (製品カタログ、ブログ投稿、ドキュメント ページ、ポケモンなど) を含むオブジェクトの配列を返すことが期待されています。データ配列内の各オブジェクトには、Algolia がそれを認識し、必要に応じて既存のデータを上書きできるように、 id
、 _id
、またはobjectID
という名前のキーが必要です。
設定オブジェクトはすべてのインデックスに適用されます。また、一般的な設定をオーバーライドする設定オブジェクトを各インデックスに個別に渡すこともできます。
設定をindexAlgolia
に渡します。
import { indexAlgolia } from 'svelte-algolia/server-side'
indexAlgolia ( algoliaConfig )
この関数は、インデックスを更新したい場所、たとえばsvelte.config.js
またはsrc/hooks.ts
(このデモ サイトのように) で呼び出すことができます。通常、これをアプリのすべての実稼働ビルドに含めます。
const defaultConfig = {
verbosity : 1 , // 0, 1 or 2 for no/some/lots of logging
partialUpdates : false , // if true, figures out diffs between existing
// items and new ones and only uploads changes, otherwise, completely
// overwrites each index on every call to indexAlgolia()
matchFields : [ ] , // (only used when partialUpdates is true) keys of fields to check
// for whether an item has changed; could e.g. be a timestamp, hash or an ID that's
// updated every time the item has changed; if not provided, items are checked for
// deep-equality to discover changes which can become slow for thousands of items
settings : { } , // an object of Algolia index settings that applies to all indices
// see https://algolia.com/doc/api-reference/settings-api-parameters for available options
// can be overridden for individual indices by passing a settings object as part of the indices array:
// indices = [{ name: `pokedex`, ..., settings: { foo: `bar` }}],
}
このパッケージをビルド プロセス (SvelteKit アプリなど) の一部として使用するには、ビルド構成でindexAlgolia
呼び出すだけです。
// svelte.config.js
// only update Algolia indices on production builds (saves API quota)
if ( process . env [ 'NODE_ENV' ] === `production` ) {
const { indexAlgolia } = await import ( `svelte-algolia/server-side` )
const algoliaConfig = {
// see above
}
indexAlgolia ( algoliaConfig )
}
<Search />
、検索インデックスにアクセスするための Algolia アプリの ID と検索キーが必要です。また、インデックス名から、そのインデックスからの検索ヒットをレンダリングする対応する Svelte コンポーネントへのマッピングも必要です。各ヒット コンポーネントは、Algolia インデックスに格納されているすべての属性を持つhit
オブジェクトをプロップとして受け取ります。
< script >
import Search from ' svelte-algolia '
import PokemonHit from ' $site/PokemonHit.svelte '
const appId = ' 0OJ5UL9OJX '
const searchKey = ' 63f563566cdd6de606e2bb0fdc291994 '
// in a real app you'd get your credentials like this:
const appId = import .meta.env.VITE_ALGOLIA_APP_ID
const searchKey = import .meta.env.VITE_ALGOLIA_SEARCH_KEY
</ script >
< header >
< nav >{ ... }</ nav >
< Search
{ appId }
{ searchKey }
indices ={{ Pokedex : PokemonHit }}
placeholder = " Search Pokedex " />
</ header >
たとえば、デモ サイトのPokemonHit.svelte
コンポーネントは次のようになります。
< script >
export let hit
</ script >
< h2 >{ @html hit . name }</ h2 >
< div >
< ul >
< li >Type: { @html hit . type . join ( ` , ` )}</ li >
< li >Height: { @html hit . height }</ li >
< li >Weight: { @html hit . weight }</ li >
< li >Weaknesses: { @html hit . weaknesses . join ( ` , ` )}</ li >
</ ul >
< img src ={ hit . img } alt ={ hit . nameOrig } />
</ div >
< style >
/* highlights text matching the search string */
:global( em ) {
color : darkcyan ;
line-height : 1.2 em ;
border-radius : 3 pt ;
font-style : normal ;
}
div {
display : flex ;
justify-content : space-between ;
}
</ style >
現在の検索文字列と一致する属性の部分文字列は<em>
でラップされます。正しく表示するには{@html ...}
タグが必要ですが、特定のヒットが現在の検索文字列と一致する理由を強調表示するようにスタイルを設定できます。強調表示されたすべての属性の元の値 (つまり、 <em>
タグなし) はhit.[attr]Orig
として使用できます。上記のhit.nameOrig
参照してください。
このコンポーネントのプロパティ/バインド可能な変数の完全なリスト:
appId: string
アルゴリアアプリID
ariaLabel: string = `Search`
入力要素をユーザーに通知する方法を支援技術に指示します。
hasFocus: boolean = false
テキスト入力ペインまたは結果ペインに現在フォーカスがあるかどうかを示すバインド可能なブール値。
indices: Record < string , typeof SvelteComponent > | [ string , typeof SvelteComponent ] [ ]
Search
コンポーネントが検索結果を見つけるために利用する各インデックスの名前を、それらのヒットをレンダリングする Svelte コンポーネントにマッピングするオブジェクト。
input: HTMLInputElement | null = null
DOM ノードへのハンドル。
loadingMsg: string = `Searching...`
検索結果の取得中に結果ペインに表示する文字列。
noResultMsg = ( query : string ) : string => `No results for ' ${ query } '`
検索結果が返されなかった場合に表示する文字列を返す関数。
placeholder: string = `Search`
ユーザーが入力を開始する前にテキスト入力に表示されるプレースホルダー。
query: string = ``
DOM ノードの現在の値。
resultCounter = ( hits : SearchHit [ ] ) : string =>
hits . length > 0 ? `<span>Results: ${ hits . length } <span>` : ``
各インデックスの名前の横に表示される文字列を返し、そのインデックスで見つかった結果の数を示す関数。何も表示しない場合は空の文字列を返します。
searchKey: string
検索専用APIキー
Search.svelte
レンダリングするすべてのヒット コンポーネントのon:close
イベントをリッスンし、受信するとhasFocus
false
に設定して自身を閉じます。これを使用すると、たとえば、ユーザーが検索結果のいずれかのリンクをクリックしてサイト上の別のページに移動したときに検索インターフェイスを閉じることができます。
< script >
import { createEventDispatcher } from ' svelte '
export let hit
const dispatch = createEventDispatcher ()
</ script >
< h3 >
< a href ={ hit . slug } on:click ={() => dispatch ( ` close ` )}>{ @html hit . title }</ a >
</ h3 >
< p >{ @html hit . body }</ p >
また、ユーザーが検索アイコンをクリックしてフォーカスがテキスト入力に入るたびに、 focus
イベントも発行されます。
< Search on:focus ={() => console . log ( " Let's search! " )} />
Search.svelte
ここにリストされている次の CSS 変数を、小道具として直接渡すことができるデフォルト (存在する場合) とともに提供します。
button
color: var(--search-icon-color)
h2
color: var(--search-heading-color)
input
background: var(--search-input-bg)
color: var(--search-input-color)
font-size: var(--search-input-font-size, 1em)
input::placeholder
color: var(--search-input-color)
input.hasFocus + button
color: var(--search-input-color)
div.results
background-color: var(--search-hits-bg-color, white)
box-shadow: var(--search-hits-shadow, 0 0 2pt black)
例えば:
< Search
indices ={{ Pages : SearchHit , Posts : SearchHit }}
{ appId }
{ searchKey }
-- hitsBgColor = " var(--search-body-bg) "
-- inputColor = " var(--search-text-color) "
-- iconColor = " var(--search-link-color) "
/>
最上位の要素はクラスsvelte-algolia
のaside
です。したがって、次のようなグローバル スタイルを定義することで、その下の DOM ツリー全体のスタイルを設定することもできます。
: global (aside.svelte-algolia input button svg) {
/* this would target the search icon */
}
: global (aside.svelte-algolia div.results section h2) {
/* this would target the heading shown above the list of results for each index */
}
本番環境でsvelte-algolia
使用しているいくつかのサイト:
studenten-bilden-schueler.de
[コード]afara.foundation
[コード]ocean-artup.eu
[コード]あなた自身でもsvelte-algolia
使用していますか?ここにサイトを追加するには PR を送信してください。
PR は歓迎ですが、変更について話し合うために、最初に問題をオープンするのが最善です。
アプリ ID と検索キー.env
意図的にコミットされているため、最初に独自のインデックスを作成しなくても、このリポジトリを複製して作業できるようになります。ローカルで実行されている開発サーバーで変更を試すには、次を使用します。
git clone https://github.com/janosh/svelte-algolia
cd svelte-algolia
sed -i.bak ' s/name: `Pokedex`/name: `Pokedex Clone`/ ' svelte.config.js
npm install
npm run dev
開発中にこのデモ サイトの検索インデックスを誤って混乱させないように、 site/svelte.config.js
内のインデックス名を'Pokedex'
から'Pokedex Clone'
に変更するsed
コマンドに注意してください。