mirror of
https://github.com/ershisan99/DevToysWeb.git
synced 2025-12-16 12:32:48 +00:00
perf: speed up search
This commit is contained in:
@@ -4,6 +4,8 @@ A web clone of [DevToys](https://github.com/veler/DevToys)
|
|||||||
|
|
||||||
## Known issues
|
## Known issues
|
||||||
|
|
||||||
|
- Tool search does not set query parameters
|
||||||
|
- [(Shallow routing) updating search params causes server code to rerun.](https://github.com/vercel/next.js/issues/49668)
|
||||||
- [Editor may not resize to fit container size](https://github.com/suren-atoyan/monaco-react/issues/346)
|
- [Editor may not resize to fit container size](https://github.com/suren-atoyan/monaco-react/issues/346)
|
||||||
- CSS outlines messed up
|
- CSS outlines messed up
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import "@/styles/globals.css";
|
import "@/styles/globals.css";
|
||||||
import { Metadata } from "next";
|
import { Metadata } from "next";
|
||||||
|
import { SearchTextProvider } from "@/contexts/search-text";
|
||||||
|
|
||||||
import { siteConfig } from "@/config/site";
|
import { siteConfig } from "@/config/site";
|
||||||
import { fontMono, fontSans } from "@/lib/fonts";
|
import { fontMono, fontSans } from "@/lib/fonts";
|
||||||
@@ -44,16 +45,18 @@ export default function RootLayout({ children }: RootLayoutProps) {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<ThemeProvider attribute="class" defaultTheme="system" disableTransitionOnChange>
|
<ThemeProvider attribute="class" defaultTheme="system" disableTransitionOnChange>
|
||||||
<div className="relative flex h-full flex-col">
|
<SearchTextProvider>
|
||||||
<SiteHeader />
|
<div className="relative flex h-full flex-col">
|
||||||
<div className="flex flex-1 overflow-y-hidden">
|
<SiteHeader />
|
||||||
<Sidebar />
|
<div className="flex flex-1 overflow-y-hidden">
|
||||||
<main className="h-full flex-1 overflow-y-auto rounded-tl-md border bg-page p-12">
|
<Sidebar />
|
||||||
{children}
|
<main className="h-full flex-1 overflow-y-auto rounded-tl-md border bg-page p-12">
|
||||||
</main>
|
{children}
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<TailwindIndicator />
|
||||||
<TailwindIndicator />
|
</SearchTextProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useSearchParams } from "next/navigation";
|
import { useSearchText } from "@/contexts/search-text";
|
||||||
import Fuse from "fuse.js";
|
import Fuse from "fuse.js";
|
||||||
|
|
||||||
import { homeTools } from "@/config/tools";
|
import { homeTools } from "@/config/tools";
|
||||||
@@ -8,9 +8,8 @@ import { PageRootSection } from "@/components/page-root-section";
|
|||||||
import { ToolCards } from "@/components/tool-cards";
|
import { ToolCards } from "@/components/tool-cards";
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const params = useSearchParams();
|
// use search params in context
|
||||||
|
const q = useSearchText();
|
||||||
const q = params.get("q")?.trim() ?? "";
|
|
||||||
|
|
||||||
const fuse = new Fuse(homeTools, { keys: ["keywords"], threshold: 0.45 });
|
const fuse = new Fuse(homeTools, { keys: ["keywords"], threshold: 0.45 });
|
||||||
const keyWordsOptions = q.split(" ").map(word => ({ keywords: word }));
|
const keyWordsOptions = q.split(" ").map(word => ({ keywords: word }));
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
import { useSetSearchText } from "@/contexts/search-text";
|
||||||
|
|
||||||
import { cn } from "@/lib/style";
|
import { cn } from "@/lib/style";
|
||||||
import { Button, ButtonProps } from "@/components/ui/button";
|
import { Button, ButtonProps } from "@/components/ui/button";
|
||||||
@@ -12,10 +13,17 @@ export function SearchBar() {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const [text, setText] = useState("");
|
const [text, setText] = useState("");
|
||||||
|
const setSearchText = useSetSearchText();
|
||||||
|
|
||||||
|
// prefetch to speed up the first search
|
||||||
|
useEffect(() => router.prefetch("/search"), [router]);
|
||||||
|
|
||||||
const search = () => {
|
const search = () => {
|
||||||
if (text.trim()) {
|
if (text.trim()) {
|
||||||
router.push(`/search?q=${text.trim()}`);
|
// next/navigation doesn't support shallow routing, use context instead of query params for speed
|
||||||
|
// https://github.com/vercel/next.js/issues/49668
|
||||||
|
setSearchText(text.trim());
|
||||||
|
router.push("/search");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
21
contexts/search-text.tsx
Normal file
21
contexts/search-text.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { PropsWithChildren, createContext, useContext, useState } from "react";
|
||||||
|
|
||||||
|
const SearchTextContext = createContext("");
|
||||||
|
const SetSearchTextContext = createContext<(text: string) => void>(() => {});
|
||||||
|
|
||||||
|
export const useSearchText = () => useContext(SearchTextContext);
|
||||||
|
export const useSetSearchText = () => useContext(SetSearchTextContext);
|
||||||
|
|
||||||
|
export const SearchTextProvider = ({ children }: PropsWithChildren) => {
|
||||||
|
const [searchText, setSearchText] = useState("");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SearchTextContext.Provider value={searchText}>
|
||||||
|
<SetSearchTextContext.Provider value={setSearchText}>
|
||||||
|
{children}
|
||||||
|
</SetSearchTextContext.Provider>
|
||||||
|
</SearchTextContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user