라이브 데모
서버 측 Algolia 색인 업데이트용 유틸리티와 Svelte 앱용 클라이언트 측 검색 구성 요소입니다. 단일 종속성만 추가합니다.
algoliasearch
algoliasearch/lite
(13KB). 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
props로 직접 전달할 수 있는 기본값(있는 경우)과 함께 여기에 나열된 다음 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
명령에 유의하세요. 그러면 개발하는 동안 실수로 이 데모 사이트의 검색 인덱스가 엉망이 되지 않습니다.