Skip to content

Commit

Permalink
feat: move search to Web Worker
Browse files Browse the repository at this point in the history
  • Loading branch information
weareoutman committed Nov 27, 2024
1 parent 3f28255 commit 15b7fba
Show file tree
Hide file tree
Showing 8 changed files with 249 additions and 200 deletions.
1 change: 1 addition & 0 deletions docusaurus-search-local/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"@node-rs/jieba": "^1.6.0",
"cheerio": "^1.0.0",
"clsx": "^1.1.1",
"comlink": "^4.4.2",
"debug": "^4.2.0",
"fs-extra": "^10.0.0",
"klaw-sync": "^6.0.0",
Expand Down
24 changes: 14 additions & 10 deletions docusaurus-search-local/src/client/theme/SearchBar/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@ import {
} from "@docusaurus/theme-common";
import { useActivePlugin } from "@docusaurus/plugin-content-docs/client";

import { fetchIndexes } from "./fetchIndexes";
import { SearchSourceFactory } from "../../utils/SearchSourceFactory";
import { fetchIndexesByWorker, searchByWorker } from "../searchByWorker";
import { SuggestionTemplate } from "./SuggestionTemplate";
import { EmptyTemplate } from "./EmptyTemplate";
import { SearchResult } from "../../../shared/interfaces";
import {
searchResultLimits,
Mark,
searchBarShortcut,
searchBarShortcutHint,
Expand Down Expand Up @@ -149,9 +147,9 @@ export default function SearchBar({
search.current?.autocomplete.destroy();
setLoading(true);

const [{ wrappedIndexes, zhDictionary }, autoComplete] = await Promise.all([
fetchIndexes(versionUrl, searchContext),
const [autoComplete] = await Promise.all([
fetchAutoCompleteJS(),
fetchIndexesByWorker(versionUrl, searchContext),
]);

const searchFooterLinkElement = ({
Expand Down Expand Up @@ -256,11 +254,17 @@ export default function SearchBar({
},
[
{
source: SearchSourceFactory(
wrappedIndexes,
zhDictionary,
searchResultLimits
),
source: async (
input: string,
callback: (output: SearchResult[]) => void
) => {
const result = await searchByWorker(
versionUrl,
searchContext,
input
);
callback(result);
},
templates: {
suggestion: SuggestionTemplate,
empty: EmptyTemplate,
Expand Down

This file was deleted.

84 changes: 0 additions & 84 deletions docusaurus-search-local/src/client/theme/SearchBar/fetchIndexes.ts

This file was deleted.

43 changes: 21 additions & 22 deletions docusaurus-search-local/src/client/theme/SearchPage/SearchPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import { usePluralForm } from "@docusaurus/theme-common";
import clsx from "clsx";

import useSearchQuery from "../hooks/useSearchQuery";
import { fetchIndexes } from "../SearchBar/fetchIndexes";
import { SearchSourceFactory } from "../../utils/SearchSourceFactory";
import { fetchIndexesByWorker, searchByWorker } from "../searchByWorker";
import {
SearchDocument,
SearchDocumentType,
Expand Down Expand Up @@ -52,10 +51,6 @@ function SearchPageContent(): React.ReactElement {
updateSearchContext,
} = useSearchQuery();
const [searchQuery, setSearchQuery] = useState(searchValue);
const [searchSource, setSearchSource] =
useState<
(input: string, callback: (results: SearchResult[]) => void) => void
>();
const [searchResults, setSearchResults] = useState<SearchResult[]>();
const versionUrl = `${baseUrl}${searchVersion}`;

Expand Down Expand Up @@ -83,19 +78,22 @@ function SearchPageContent(): React.ReactElement {
useEffect(() => {
updateSearchPath(searchQuery);

if (searchSource) {
if (searchQuery) {
searchSource(searchQuery, (results) => {
setSearchResults(results);
});
} else {
setSearchResults(undefined);
}
if (searchQuery) {
(async () => {
const results = await searchByWorker(
versionUrl,
searchContext,
searchQuery
);
setSearchResults(results);
})();
} else {
setSearchResults(undefined);
}

// `updateSearchPath` should not be in the deps,
// otherwise will cause call stack overflow.
}, [searchQuery, searchSource]);
}, [searchQuery, versionUrl, searchContext]);

const handleSearchInputChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
Expand All @@ -110,17 +108,18 @@ function SearchPageContent(): React.ReactElement {
}
}, [searchValue]);

const [searchWorkerReady, setSearchWorkerReady] = useState(false);

useEffect(() => {
async function doFetchIndexes() {
const { wrappedIndexes, zhDictionary } =
if (
!Array.isArray(searchContextByPaths) ||
searchContext ||
useAllContextsWithNoSearchContext
? await fetchIndexes(versionUrl, searchContext)
: { wrappedIndexes: [], zhDictionary: [] };
setSearchSource(() =>
SearchSourceFactory(wrappedIndexes, zhDictionary, 100)
);
) {
await fetchIndexesByWorker(versionUrl, searchContext);
}
setSearchWorkerReady(true);
}
doFetchIndexes();
}, [searchContext, versionUrl]);
Expand Down Expand Up @@ -198,7 +197,7 @@ function SearchPageContent(): React.ReactElement {
) : null}
</div>

{!searchSource && searchQuery && (
{!searchWorkerReady && searchQuery && (
<div>
<LoadingRing />
</div>
Expand Down
47 changes: 47 additions & 0 deletions docusaurus-search-local/src/client/theme/searchByWorker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as Comlink from "comlink";
import { SearchResult } from "../../shared/interfaces";

interface RemoteWorker {
fetchIndexes(baseUrl: string, searchContext: string): Promise<void>;
search(
baseUrl: string,
searchContext: string,
input: string
): Promise<SearchResult[]>;
}

let remoteWorkerPromise: Promise<RemoteWorker> | undefined;

function getRemoteWorker() {
if (!remoteWorkerPromise) {
remoteWorkerPromise = (async () => {
const Remote = Comlink.wrap(
new Worker(new URL("./worker.js", import.meta.url))
) as any;
return await new Remote();
})();
}
return remoteWorkerPromise;
}

export async function fetchIndexesByWorker(
baseUrl: string,
searchContext: string
): Promise<void> {
if (process.env.NODE_ENV === "production") {
const remoteWorker = await getRemoteWorker();
await remoteWorker!.fetchIndexes(baseUrl, searchContext);
}
}

export async function searchByWorker(
baseUrl: string,
searchContext: string,
input: string
): Promise<SearchResult[]> {
if (process.env.NODE_ENV === "production") {
const remoteWorker = await getRemoteWorker();
return remoteWorker!.search(baseUrl, searchContext, input);
}
return [];
}
Loading

0 comments on commit 15b7fba

Please sign in to comment.