Hugo 本地搜索

Photo by Nine Köpfer on Unsplash

静态博客的搜索功能实现基本上可以分为两种:第一种是生成所有数据,客户端下载这些数据并进行搜索;第二种是借助第三方服务来进行索引,并返回匹配的数据。

前一种实现起来很简单,毕竟不需要研究第三方API。但如果需要搜索的数据非常大,或者是客户端的性能不够就容易导致卡顿。

这篇文章就写写第一种在Hugo上的实现方法好了。

想法

  1. Hugo 生成全站文章的数据,以JSON格式保存
  2. 浏览器下载这些数据
  3. 前端找个JS插件来索引数据 (Lunr, Fuse…)
  4. 返回匹配数据,并渲染列表

实现

我把写好的模板放到了Gist上,如果你看不见上面的内容,请自行搜索科学上网。

配置

我使用了Fuse这个库来做索引。当然也你也可以换其他的JS库,我只是随便找了个能用的…

index.json这个文件需要放到你的模板目录下的partials下,同时修改博客根目录的config.toml,加入下面这段:

[outputs]
home = ["HTML", "RSS", "JSON"]

生成的JSON会存放在博客的根目录,可以通过domain.com/index.json来访问。

index.json里你会发现,目前输出的内容有:

  • title : 标题
  • date : 日期
  • url: 地址
  • tag: 标签。请注意,我使用的是.Params.tag,而不是.Params.tags
  • content: 概要,并不是全文

目前只会搜索文章的概要、标签和标题,如果需要搜索更多内容,可以修改search.js的第11行。虽然我并不推荐搜索全文,因为数据会太大,导致速度变慢。

脚本里面用到了fetch和ES6的Template Strings。后者不被IE支持,所以如果需要兼容的话还是慢慢拼字符串吧。(search.js 67 - 90 行)😂

如果让我选,我选择放弃IE,这样写模板多舒服…

另外,在search.js开头有个searchOptions,那是Fuse的设置,可以到官网查询每个选项的意思。

我认为最重要的还是threshold。修改这个值 ([0, 1]) 可以更改搜索的准确度,越小越准确。


最后,你需要创建一个页面,并在Frontmatter注明layout: 'search',例如:

---
title: "搜索"
date: '2017-07-22'
slug: "search"
layout: 'search'
---

最后

如果你的博文很多,不推荐使用此方法进行搜索:容易拖慢生成速度不说,客户端也要下载大量数据&处理。

我现在文章数量还不多,先暂时用着,但很有可能我以后会换Google Custom Search,用起来更舒服。


Originally Published on Jul 22, 2017 at Journey
A single golf clap? Or a long standing ovation?

By clapping more or less, you can signal to us which stories really stand out.