검색 엔진도 없고 음 검색 기능도 없는 사전이 뭐죠!?
기본 사전을 구현하는 동안 이 특정 기능을 준비하기 위해 정적 검색 양식(홈페이지에 하나, 단어 레이아웃에 사용되는 Navbar에 하나)을 만들었습니다.
그냥 바로 거기에서 픽업해서 제대로 작동하게 하고 싶었어요. 그게 사실이라면 말이죠.
과거의 것
초기 커밋에서 다음과 같이 인정했듯이 초기 계획은 Nextra를 사용하여 jargons.dev를 구축하는 것이었음을 다시 한 번 강조하는 것이 중요합니다.
...Nextra(사실 이것은 빛나는 갑옷을 입은 나의 기사였습니다. 저는 Nextra로 구축하려고 했습니다).
저는 Next.js를 좋아하는 React ⚛️ 팬입니다. Nextra는 Next.js를 기반으로 구축된 콘텐츠 중심 웹 프레임워크입니다. 그러면 Nextra가 왜 그 기사처럼 들렸는지 이해할 수 있을 것 같습니다. Nextra를 처음 탐색하는 동안 한 가지 기능이 눈에 띄었습니다. 전체 텍스트 검색 — 나는 이것 때문에 침을 흘렸습니다(고백해야겠습니다).
이 기능은 제로 깊이 전체 텍스트 검색 라이브러리인 flexsearch에 의해 구동되었습니다. 이런, 저는 가볍고 의존성이 없거나 낮은 것을 좋아합니다. 나는 Nextra가 이것을 사용하여 검색을 위한 빌드 타임에 콘텐츠를 색인화하는 방법을 파헤쳤습니다. 흥미로웠어요.
그래서!?
저는 Astro를 처음 접했을 때 Flexsearch를 사용하여 해킹하고 있는 것을 발견했습니다. Astro doc의 블로그 구축 튜토리얼을 따라하면서 검색 기능을 매우 쉽게 구현하기 위해 한 단계 더 나아갔습니다.
이번 구현을 통해 얻은 경험은 다음과 같습니다. jargons.dev를 검색 엔진에 전달했습니다.
검색 엔진
작업은 꽤 간단해서...
- 단어 사전 디렉터리 내부의 모든 파일에 대한 액세스 권한을 얻거나 참조라고 부릅니다. 이 시점에서는 src/pages/word 디렉터리였습니다.
- Flexsearch를 사용하여 이러한 파일 콘텐츠의 색인을 생성하세요.
- 검색 양식을 입력하고 붐을 일으키세요 ?
아주 쉬워 보이는데요! 아마도 검색 인덱싱과 실제 검색을 위해서였을 것입니다. 하지만 거기까지 가는 데에는 많은 것들이 필요했습니다.
jargons.dev에 첫 번째 "섬" 통합
Astro는 기본적으로 서버 우선 접근 방식을 취합니다. 즉, 달리 명시하지 않는 한 모든 클라이언트 측 자바스크립트(JS)를 자동으로 제거하여 서버에 사이트의 HTML/CSS를 구축한다는 의미입니다. JS를 모두 제거하면 성능이 향상되지만 JS가 없으면 상호 작용이 없음을 의미합니다. 그러나 상호 작용을 원한다면 Astro Island가 좋은 방법 중 하나입니다. 검색 엔진에 대한 상호작용이 필요하므로 Island입니다!
그런데 "섬"이란 무엇입니까!?
간단히 말하면 Island는 웹 페이지에 있는 격리된 대화형 구성 요소로, HTML/CSS가 서버 측에서 렌더링되고/하지만 클라이언트 측 JavaScript도 (수화) 함께 번들로 제공됩니다. 제거되지 않았습니다.
TILConf'24에서 Island에 대해 강연한 적이 있습니다. 자세한 내용은 확인해보세요.
Astro의 제안
Astro는 내가 가장 좋아하는 UI 라이브러리(예, 짐작하셨겠지만 React)와 Island를 즉시 통합할 수 있는 지원을 제공했습니다. 이를 통해 정적 검색 양식을 기능적인 항목으로 만들 수 있었습니다.
내가 한 일들
- 통합해야 하는 섬에 통합 모듈(@astrojs/react)을 추가하는 것부터 시작했습니다. npx astro add React 명령
을 사용하면 매우 쉽게 완료됩니다.
- 모든 정적 검색 양식을 단일 React 구성 요소로 옮겼습니다(이들은 크기가 다른 두 가지 양식입니다). 주어진 소품을 기반으로 필요한 크기로 렌더링하도록 구성 요소를 구성했습니다.
- 또한 동일한 검색 구성 요소에서 로컬로만 사용되는 일부 하위 구성 요소를 구현했습니다.
- SearchDialog - 검색 작업이 수행되는 주요 구성 요소
- SearchResult 구성요소 등...
- 검색 구성 요소(이제부터 "검색 섬"이라고 부르고 싶습니다)와 상호 작용할 수 있는 몇 가지 사용자 정의 키보드 단축키와 키 바인드를 구현했습니다. 이는 다음과 같습니다.
-
검색을 시작하려면 CTRL K 또는 ⌘K를 누르세요
-
검색을 닫으려면 ESC
- ...검색 결과 내에서 탐색하려면 기본 필수 탐색 버튼이 필요합니다.
- 또한 검색 섬 작업을 원활하게 수행할 수 있도록 몇 가지 사용자 정의 후크를 추가했습니다. 이것은...
-
useLockBody - 검색 대화 상자가 열리면 스크롤을 비활성화하는 후크
-
useRouter - 일부 window.location 메서드 주위에 래퍼로 만든 후크로 React에서 알려진 라우터 라이브러리처럼 느껴지도록 했습니다. 이는 특히 검색 결과 구성 요소의 탐색 버튼 키 바인딩에 있는 ENTER 버튼 클릭 핸들러에서 사용한 후크입니다. 검색 섬에서.
- and useIsMacOS - 검색 양식 트리거에 렌더링할 적절한 설명 텍스트를 결정하기 위해 시스템이 MacOS인지 확인합니다. 즉, CTRL K 또는 ⌘K
- 명령형 모듈인 flexsearch를 추가했습니다.
- Astro.glob() 함수를 사용하여 매우 쉽게 단어 디렉터리에 있는 파일에 대한 액세스를 검색했습니다. (안타깝게도 이 함수가 얼마나 강력한지 말할 수 없었습니다. Astro에 바로 사용할 수 있어서 얼마나 다행인지 모릅니다. 그리고 이 검색 엔진을 시작하고 실행하는 흐름을 얼마나 쉽게 가져왔는지) 반환된 단어 개체 배열을 nanostore(바로 또 다른 아름다운 항목)에서 제공하는 $dictionary 상태(아마도 이것을 저장소라고 불러야 할 것임)에 연결했습니다.
- 이 $dictionary는 flexsearch로 색인화되어 나중에 검색할 수 있도록 준비됩니다.
또 다른 필수 기능: 최근 검색
이것은 제가 이야기해야 할 또 다른 필수 기능입니다. 이 기능은 검색된 항목을 추적하고 로컬 저장소에 저장하여 페이지를 다시 로드할 때 유지합니다. 매장에서 검색한 항목은 사전 홈페이지의 목록으로 렌더링됩니다.
또한 나노스토어 기반 $recentSearches 상태에서 가치를 보유하는 섬과 결합하여 통합되었습니다.
이 기능의 구현은 완벽하지는 않습니다. 여기에 한 단계 더 나아가기 위해(작성 당시) 수정이 필요한 몇 가지 문제 목록이 있습니다(비록 완벽에 도달할 수는 없지만 그렇습니다. 물론이죠)
- 최근 검색 섬에 로딩 구성 요소 추가 - https://github.com/devjargons/jargons.dev/issues/31
- 버그: Navbar의 검색 양식으로 수행된 검색 작업이 LocalStorage를 덮어씁니다 - https://github.com/devjargons/jargons.dev/issues/10
- 향상: Word Editor - 두 번째 반복 기능 - https://github.com/devjargons/jargons.dev/issues/9
홍보
이제 읽은 내용이 길어졌습니다. 짧게 읽고 싶습니다... PR은 다음과 같습니다.
특기: 사전 검색 엔진 구현
#5
이 Pull Request는 사전 프로젝트에 검색 기능을 구현합니다. @astro/react 통합을 사용하여 상태 관리를 위한 nanostore와 텍스트 검색 라이브러리인 flexsearch를 결합하여 Island를 강화합니다.
변경사항
- 텍스트 검색에 필요한 다음 astrojs 통합 및 lib를 추가했습니다.
- @astrojs/반응
- @nanostores/반응
- 플렉스서치
- 내부 사용을 위해 다른 하위 구성 요소가 구현되는 곳에 Search Island(반응 구성 요소)를 구현했습니다.
- 두 가지 크기의 검색 필드를 렌더링하고 웹 페이지의 두 위치에서 사용되는 SearchTrigger 구성 요소를 구현했습니다...
- md 크기 - 웹 앱의 메인 페이지에 사용됩니다.
- 크기 sm - 사전 단어 레이아웃 탐색 섹션에 사용됨
- SearchTrigger를 클릭할 때만 렌더링되는 SearchDialog 구성요소를 구현했습니다.
- SearchInfo 구성 요소를 구현했으며, 양식 필드에 검색어가 입력되지 않은 경우 기본 자리 표시자로 렌더링됩니다.
- SearchResult 구성 요소를 구현하여 검색 결과를 찾을 수 없거나 검색 결과에 대한 메시지를 렌더링합니다.
- 지정된 키보드 단축키로 다음 작업을 수행할 수 있도록 검색 섬 내에 키 바인딩을 구현했습니다.
-
검색 트리거
를 클릭하지 않고 검색 대화 상자를 열려면 CTRL K 또는 ⌘K를 누르세요.
-
검색 결과 목록에서 탐색을 허용하려면 ArrowUp, ArrowDown 및 Enter를 누르세요.
-
검색 대화 상자를 닫는 것을 허용하는 ESC
- 검색 섬에서 소비할 수 있는 맞춤 후크를 추가했습니다.
-
useIsMacOS - 현재 사용자가 MacOS 시스템으로 웹 앱을 탐색하고 있는지 확인합니다. 이는 검색 트리거에서 렌더링할 적절한 단편을 결정하는 데 사용됩니다. 즉, CTRL K 또는 ⌘K
-
useLockBody - 검색 대화 상자가 열릴 때 현재 뷰포트의 스크롤을 비활성화하는 데 사용됩니다.
-
useRouter - (deps에 반응 라우터를 추가하는 대신) 이 후크는 window.location을 감싸고 할당 개체를 푸시로 사용합니다. 주로 SearchResult 구성요소에서 선택/클릭한 결과 페이지로 라우팅하는 데 사용됩니다.
- Flexsearch의 문서 방법을 기본 옵션으로 사용하여 검색 섬에 searchIndexing을 구현했습니다.
- nanostores 및 @nanostores/react 통합을 통해 검색 관련 상태를 관리하기 위한 새로운 검색 스토어를 추가했습니다.
- 다음 매장 가치 및 작업을 추가했습니다.
-
$isSearchOpen - SearchDialog 상태를 관리하기 위한 전역 상태
-
$recentSearches - 최근 검색된 단어를 추적하는 상태입니다. 탭을 다시 로드한 후에도 값을 유지하기 위해 localStorage와 협력하여 작동합니다.
-
$addToRecentSearchesFn - $recentSearches 매장 가치에 새 항목을 추가하는 매장 작업
- 전체 사전 항목을 관리하기 위해 $dictionary 저장소를 추가했습니다. 클라이언트가 액세스할 수 있도록 유지하고 검색 아일랜드의 searchIndex 값으로 사용됩니다.
- 전체 사전 디렉터리를 인덱싱하는 Astro.glob() 메서드를 사용하여 레이아웃/베이스에서 가능한 한 빨리 사전 저장소에 대해 계산된 값
- $recentSearches 스토어에서 값을 읽고 이를 홈페이지에 렌더링하는 RecentSearches 아일랜드를 추가했습니다.
스크린캐스트
전체 데모
screencast-bpconcjcammlapcogcnnelfmaeghhagj-2024.03.25-13_32_30.webm
?
GitHub에서 보기