5分钟搞定!给Next.js项目集成Algolia DocSearch搜索功能

🧑‍💻
推荐全栈学习资源:
  • Next.js 中文文档:样式和官网一样的中文文档,创造沉浸式Next.js中文学习体验。
  • 《Chrome插件全栈开发》:真实出海项目的实战教学课,讲解Chrome插件和Next.js端的全栈开发,帮助你半个月内成为全栈出海工程师。
  • 前言

    半年前,我开源了一个 Next.js 博客模板。当时为了实现站内搜索,我选择了 FlexSearch 方案。FlexSearch 是一个高性能的全文搜索库,在英文环境下表现优异。然而在实际测试中,我发现中文搜索存在严重问题。要解决这个问题,就需要引入 nodejieba 这样的中文分词库。但 nodejieba 依赖 C++ 编译环境,而我的网站都是部署在 serverless 环境,无法直接支持,所以那时候我只在模板里放了一个简化版的搜索,使用体验并不好。

    因为搜索功能使用频率太低了,所以我后来就没怎么研究了。直到和阿伟一起开发 Next.js 中文文档 的时候,阿伟给文档站集成了 Algolia DocSearch,我才重新准备修改博客模板的搜索功能。让我惊讶的是,集成 DocSearch 太方便了,我花了5分钟就上线新的搜索功能。

    💡
    本文首发于我的博客J实验室
    欢迎加入「🌍全栈出海交流群」 和「🧑‍💻Next.js 技术交流群」, 一起交流出海信息和全栈技术

    Algolia DocSearch 简介

    Algolia 提供了付费的企业版和免费的 DocSearch 两种方案。DocSearch 专门针对技术文档、博客等内容网站,只要你的网站是公开可访问的,就能免费集成。

    DocSearch 凭借专业的搜索能力和丝滑的用户体验,已经成为技术文档的主流搜索方案。连 React 和 Vue 这样的官方网站都在使用。

    这篇教程将手把手带你在 Next.js 项目中集成 DocSearch,只需跟随以下步骤,你也能很快为网站添加专业级的站内搜索。

    1、申请 DocSearch

    1. 填写表单申请:https://docsearch.algolia.com/apply/

    2. 等待 Algolia 团队的邮件,等待了一天,我就收到了这样的一封邮件:

      email.webp

    收到邮件就表示 Algolia 已经索引好了我们的网站,现在就可以集成了。注意圈起来的参数,后面开发的搜索框组件需要使用这三个核心参数。

    2、代码集成

    安装依赖

    # 使用 npm
    npm install @docsearch/css @docsearch/react
     
    # 使用 yarn
    yarn add @docsearch/css @docsearch/react
     
    # 使用 pnpm
    pnpm add @docsearch/css @docsearch/react

    创建配置文件 config/docSearchConfig.ts

    interface DocSearchConfig {
      docSearch: {
        appId: string;
        indexName: string;
        apiKey: string;
      }
    }
     
    export const docSearchConfig: DocSearchSiteConfig = {
      docSearch: {
        appId: "填写邮件收到的参数",
        indexName: "填写邮件收到的参数",
        apiKey: "填写邮件收到的参数",
      },
    }

    创建 DocSearch 搜索框组件 components/DocSearch/index.ts,实现一个功能完备的搜索组件:

    "use client";
     
    import { docSearchConfig } from "@/config/docSearch";
    import "@docsearch/css";
    import { DocSearchModal, useDocSearchKeyboardEvents } from "@docsearch/react";
    import Link from "next/link";
    import { useCallback, useEffect, useRef, useState } from "react";
    import { createPortal } from "react-dom";
    import { IoIosSearch } from "react-icons/io";
    import "./docSearch.css";
     
    export default function CustomDocSearch() {
      const { appId, indexName, apiKey } = docSearchConfig.docSearch;
      const [isOpen, setIsOpen] = useState(false);
      const [isMac, setIsMac] = useState(false);
      const searchButtonRef = useRef<HTMLButtonElement>(null);
     
      const onOpen = useCallback(() => {
        setIsOpen(true);
      }, [setIsOpen]);
     
      const onClose = useCallback(() => {
        setIsOpen(false);
      }, [setIsOpen]);
     
      useDocSearchKeyboardEvents({
        isOpen,
        onOpen,
        onClose,
        searchButtonRef,
      });
     
      // 添加检测操作系统的效果
      useEffect(() => {
        setIsMac(navigator.platform.toUpperCase().indexOf("MAC") >= 0);
      }, []);
     
      return (
        <>
          <button className="docSearch-btn" data-variant="large" onClick={onOpen}>
            搜索文档<kbd>{isMac ? "⌘K" : "Ctrl+K"}</kbd>
          </button>
          <button className="docSearch-btn" data-variant="medium" onClick={onOpen}>
            搜索<kbd>{isMac ? "⌘K" : "Ctrl+K"}</kbd>
          </button>
          <button
            className="docSearch-btn mr-2 hover:bg-accent border border-gray-300"
            data-variant="small"
            onClick={onOpen}
          >
            <IoIosSearch />
          </button>
          {isOpen &&
            createPortal(
              <DocSearchModal
                initialScrollY={window.scrollY}
                appId={appId}
                apiKey={apiKey}
                indexName={indexName}
                onClose={onClose}
                placeholder="搜索文档"
                hitComponent={({ hit, children }) => (
                  <Link href={hit.url}>{children}</Link>
                )}
              />,
              document.body
            )}
        </>
      );
    }

    docSearch.css 是自定义的搜索样式,这部分不重要,不贴代码了,你可以到文末的开源地址查看。

    再把搜索框组件 CustomDocSearch 引入 Header 就可以使用了。

    总结

    DocSearch 的搜索和集成都非常方便,现在我的博客模板博客信息差周刊都已经集成好了,这三个项目都是开源的,你可以直接复制我的组件代码。

    也可以到「Next.js中文文档」体验,文档站一共有 300 多个文档,搜索效率依然非常高,所以你完全可以放心使用。

    关于我

    我是一名全栈工程师,Next.js 开源手艺人,AI降临派。

    今年致力于 Next.js 和 Node.js 领域的开源项目开发和知识分享。

    欢迎在以下平台关注我: