前言:

DevNow 项目中我们使用了 DocSearch 来实现搜索功能,但是由于有以下的限制:

  1. 您的网站必须是技术文档或技术博客。
  2. 您必须是网站的所有者,或者至少具有更新其内容的权限
  3. 您的网站必须公开可用
  4. 您的网站必须已准备好生产环境。

由于这些条件的限制, DocSearch 只适合用在开源的技术文档或技术博客中,所以从 DevNow 开源博客项目的定位来说,还是比较适适合的。为什么突然想着要优化一下搜索组件呢?

今天心血来潮想在 blog 上找一篇文章,用搜素的功能发现搜不出来,搜索挂了?然后突然想起来之前由于想着在 blog 中可能加一些私有的配置或者尝鲜的功能,所有 fork 了一份变成 私有项目了,这样就不符合 DocSearch 的 网站必须是公开的这个限制了。

其实用下来我个人感觉还有以下几点不是很满意的地方:

  1. 配置麻烦,需要在 Algolia 上注册账号,然后创建一个应用,然后在项目里配置一些 api-key 信息。
  2. 搜索信息索引的配置可能需要自己在平台上定制化一些 config ,开始可能会比较迷茫。
  3. 索引可能会不及时,默认一周会重新索引一次,所以刚发布的文章可能无法被搜索到。

所以一怒之下就想着改一下,之前想着看看其他的方案,之前在在 shadcn/ui 中看到了一个 Command + K 的搜索组件,所以就想着能不能在 DevNow 中也实现一下。这个实现的方案是基于 cmdk 这个库来实现的, Nextjs 官网应该也是这个实现方案。

集成 shadcn/ui

在这里还是推荐使用 shadcn/ui 来集成,因为它提供了很多的组件,而且还提供了一些 hooks 来帮助我们实现一些功能。想着后续可能还会用到一些组件,所以就直接集成了,不得不说这个UI库的样式真是深得我心啊。

安装的话直接跟着 文档 来就好,提供了一些常见框架的集成:

:::tip[注意]

在安装前要先在 tsconfig.json 中配置好 resolve paths

@/* 这个是必须有的,否则 shadcn/ui 无法初始化成功

{
"compilerOptions": {
// ...
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"] // <--- 这个必须有
}
// ...
}
}

:::

安装 Command

文档在 这里

pnpm dlx shadcn@latest add command

一个简单的例子



const Search: FC<Props> = ({ category }) => {
const [open, setOpen] = useState(false);
useEffect(() => {
const down = (e: KeyboardEvent) => {
if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {
e.preventDefault();
setOpen((open) => !open);
}
}; document.addEventListener('keydown', down);
return () => document.removeEventListener('keydown', down);
}, []); return (
<div className='mr-4 hidden items-center lg:flex'>
<Button
onClick={() => setOpen((open) => !open)}
size='sm'
className='h-[32px] bg-muted/50 px-2 py-0 text-sm text-muted-foreground shadow-none hover:bg-accent focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring'
>
Search
<kbd className='pointer-events-none ml-1 inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100'>
<span className='text-xs'>⌘</span>K
</kbd>
</Button> {config.search && (
<CommandDialog open={open} onOpenChange={setOpen}>
<CommandInput placeholder='Type a command or search...' />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
{category.map((item, index) => (
<Fragment key={index}>
<CommandGroup heading={item.label}>
{item.children.map((child, cIndex) => (
<CommandItem
// 这里需要注意的是:
// 选项点击选中的事件是 onSelect 不是 onClick
onSelect={() => {
window.open(`${location.origin}/posts/${child.id}`, '_blank');
}}
key={cIndex}
className='cursor-pointer'
>
<span>{child.label}</span>
</CommandItem>
))}
</CommandGroup>
{index === category.length - 1 && <CommandSeparator />}
</Fragment>
))}
</CommandList>
</CommandDialog>
)}
</div>
);
};

效果展示:

使用 DocSearch

使用 command 替换后:

大家觉得哪个更好呢,我个人觉得新版的会更加简洁一点。

遇到的问题

第一版的实现到这里就结束了,然后上线后发现了问题。发现线上的环境突然变卡了,请求也变多了,一看发现堵了很多请求:

然后就是定位问题,发现原因是: 当我在 Astro 中集成 React 框架时,如果组件是运行要求在客户端运行时:

<Search client:only='react' />

在通过 client:only 来标记的组件中获取所有文件的标题时,会把所有的请求一遍,这里我的理解是在客户端没有这些信息,所有执行的时候会构建一份。

这里如果改下数据源,将数据传递给 Search的话,可以规避掉这个问题。


<Search category={category} client:only='react'>

原文链接:https://www.laughingzhu.cn/posts/cdmk

搜索组件优化 - Command ⌘K的更多相关文章

  1. Django学习---组合搜索组件

    组合搜索组件 我们都会写博客,写文章之后我们要给文章设置目录,设置类型.之后我们在浏览文章的时候就能够按类别进行精确定位到文章,那这个组合搜索我们应该怎么做呢? 首先我们先创建3张表,分别存放文章,文 ...

  2. Django之组合搜索组件(二)--另附simple_tag的创建使用方法

    这次的代码为Django之组合搜索组件(一)的改版,实现的结果和(一)相同,不同的是,这次运用simple_tag方式,使.html程序简化 所以现在就开始编程吧! 首先想使用simple_tag方法 ...

  3. 搜索实时个性化模型——基于FTRL和个性化推荐的搜索排序优化

    本文来自网易云社区 作者:穆学锋 简介:传统的搜索个性化做法是定义个性化的标签,将用户和商品通过个性化标签关联起来,在搜索时进行匹配.传统做法的用户特征基本是离线计算获得,不够实时:个性化标签虽然具有 ...

  4. 如何在个人博客引擎 Hexo 中添加 Swiftype 搜索组件

    在您现在看到的我的博客站点,后台使用的是 Hexo 作为博客引擎,但是默认集成的搜索组件是进行 form 提交到 Google 进行搜索的,为了更好地体验,本文介绍如何在 Hexo 博客中集成 Swi ...

  5. Angular4.x 自定义搜索组件

    Angular4 随笔(三)  ——自定义搜索组件 1.简介 本组件主要是实现了搜索功能,主要是通过父子组件传值实现. 基本逻辑: 1.创建一个搜索组件,如:ng g component  searc ...

  6. redis的搜索组件 redis-search4j

    redis-search4j是一款基于redis的搜索组件. 特点 1.基于redis,性能高效 2.实时更新索引 3.支持Suggest前缀.拼音查找(AutoComplete功能) 4.支持单个或 ...

  7. 「小程序JAVA实战」小程序开源搜索组件(53)

    转自:https://idig8.com/2018/09/22/xiaochengxujavashizhanxiaochengxukaiyuansousuozujian52/ 上次说了可以在视频中通过 ...

  8. vue 城市搜索组件

    1.实现大致是如下效果 2.搜索组件的页面结构 <template>    <div>     <div class="search">     ...

  9. InfoQ —— 百度搜索速度优化

    本篇源自InfoQ —— <百度搜索速度优化> 好多名词不了解... 相关文档下载链接 背景 许霞,毕业于浙江大学.08年加入百度运维部. 本篇讲座主要讲述百度关于速度的优化,包括PC端和 ...

  10. Elasticsearch 调优之 搜索速度优化

    本章讨论搜索速度优化:搜索速度与系统资源.数据索引方式.查询方式等多方面 1.为文件系统cache预留足够的内存 1)应用程序一般情况下,读写都会被操作系统“cache” 2)cache保存在物理内存 ...

随机推荐

  1. 新一代Java高性能构建工具Maven-mvnd【实践可行版】

    Maven-mvnd介绍 Maven 的优点是稳定可靠,在绝大多数的项目上工作良好,社区生态很完善,几乎所有的 Java 开发者都在用.Maven 的缺点是,对于大一点的项目来说,构建太慢了.有时候只 ...

  2. 输入Javac提示不是内部或外部命令

    先去百度搜索"jdk下载"下载最新版jdk,并安装,安装目录不用去更改,直接默认就好,下载完了之后,双击打开安装,jdk安装完成后,会接着安装jre包,(jre和jdk是配对的,不 ...

  3. 经典面试题函数柯里化: add(1)(2)(3) = 6

    function currying() { const args = Array.prototype.slice.call(arguments); const inner = function () ...

  4. [oeasy]python0078_变量部分总结_variable_summary

    删除变量 回忆上次内容 上次研究了变量的死 有生就有死 原本的死是在程序退出的时候自动执行的 也可以手动给变量执行死刑 del     del(a)之后 dir()就无法在当前作用域(scope)内观 ...

  5. [oeasy]python0030_设置路径_export_PATH_zsh_系统路径设置_export

    ​ 放入路径 回忆上次内容 我们要在任意路径下直接执行 sleep.py 把 sleep.py 放在 /usr/bin/ 下面 最终可以在任意位置执行程序sleep.py 但是 /usr/bin 里面 ...

  6. Vue Axios二次封装

    // axios二次封装 import axios from 'axios' import qs from 'qs' /*** *判断环境变量区分接口的默认地址 */ switch (process. ...

  7. 记一次springboot整合rabbitMQ的list序列化问题

    问题:平时传一个类的时候都会继承Serializable实现正确传输,这次我把list<Object>直接丢成了message,导致rabbitMQ不能序列化对象.报错 org.sprin ...

  8. Ubuntu16.04设置静态IP或动态ip(DHCP)

    Ubuntu16.04设置静态IP或动态ip(DHCP) 设置静态IP 1,vim编辑/etc/network/interfaces 网络配置文件 sudo vim /etc/network/inte ...

  9. Python异常处理try+except用法

    1.except是用来捕获程序异常的 异常代码如: ModuleNotFoundError(没有找到模块,安装提示的模块即可) AttributeError(没有访问属性) TypeError(类型错 ...

  10. GeoScene Pro处理并发布倾斜摄影(OSGB)

    前言 看了网上好多教程,很多都不全,在自己操作的过程中遇到了很多问题,最后将我完整的流程整理出来,以供大家参考 从数据处理.优化.发布.加载完整流程都有 一.数据格式转换 1.全局搜索"创建 ...