在目前的博客生态圈中,静态博客占了相当大的比例。静态博客因为足够轻量、便于备份和迁移而受到包括我在内的许多用户喜欢,但由于静态博客没有数据库,在组织内容上就不免有所不足,这就涉及到题中所说的搜索功能了。为静态博客部署搜索功能比较麻烦,一个稍简单的方法就是借于「必应」「谷歌」等搜索引擎的 API,用它们来搜索站内的内容,但是这种方法的效果并不好,如果网页还未被收录或是相应头键字在网页中的占比太小,就很难搜索到目标信息。另一种方法就是在站内建立本地的搜索,例如 Hexo 等博客框架都提供了相应的插件,在本地生成搜索匹配所需的文件,将其一并推送至服务器实现全站搜索,这种方法的兼容性、准确性都要更好,也是我选择的方案。
Pelican 也有类似的搜索插件 pelican-plugins/search,它主要是借助了 Stork 来实现搜索功能。Stork 在官方文档中指出,它可以用于为静态站点构建关速美观的搜索接口,所以理应可以用于所有类型的静态博客,我不了解其他博客框架是否使用了这个工具,但不得不提其搜索体验非常不错,十分值得一试。
安装 Stork
安装 C++ 生成工具
Stork 是基于 Rust 构建的工具,需要使用 Rust 的包管理器 Cargo 安装,若是在 macOS 或 Linux 系统上,直接按照官方文档给出的方法安装即可,而在 Windows 上就会比较麻烦,我在这里介绍一下 Windows 的操作方法。
Note 后文所涉及的操作系统都是 Windows 10 系统,终端指的是 Windows 终端(Windows Terminal)。
首先,在 Windows 上,Rust 需要某些 C++ 生成工具,可以选择安装 Visual Studio 或仅安装 Microsoft C++ 生成工具。安装 Visual Studio 的方法非常简单(推荐),按下不表,若仅安装 Microsoft C++ 生成工具,可以在终端中输入
winget install Microsoft.VisualStudio.2022.BuildTools
由于 winget 下载速度感人,实在不推荐这种方法。
在安装好 Visual Studio 后,在开始界面搜索并打开 Visual Studio Installer,选择 修改
- 使用 C++ 的桌面开发
,等待安装完成。
安装 Rust
Rust 也可以使用 winget 安装,命令很简单:
winget install rustup
但是不太好用,所以我还是选择到 Rust 官网下载。下载完成后打开安装程序,弹出的是命令行窗口,默认安装在 C:\Users
路径下的目录中,如果不需要额外的设置,键入 1
后按回车即可。
但由于 C 盘空间不太够了,我需要修改一下安装的路径,在目标路径下创建以下两个文件夹并新建环境变量:
CARGO_HOME: E:\RUST\.cargo
RUSTUP_HOME: E:\RUST\.rustup
在 PATH
中添加变量 %CARGO_HOME%
、%RUSTUP_HOME%
和 %CARGO_HOME%\bin
,然后再打开安装程序,默认路径就已经改变,键入 1
按回车安装。
Rustup metadata and toolchains will be installed into the Rustup
home directory, located at:
E:\RustT\.rustup
This can be modified with the RUSTUP_HOME environment variable.
The Cargo home directory is located at:
E:\Rust\.cargo
This can be modified with the CARGO_HOME environment variable.
The cargo, rustc, rustup and other commands will be added to
Cargo's bin directory, located at:
E:\Rust\.cargo\bin
安装完成后,在终端中输入 cargo --version
理应输出版本信息。
通过 Cargo 安装 Stork
虽然安装好了 Cargo,但不出意外的话,与其他包管理器类似,从官方的源下载内容的速度非常之慢,所以需要修改配置使用镜像源。
在 .cargo
目录下创建文件 config.toml
,写入以下内容:
[source.crates-io]
replace-with = 'ustc'
[source.ustc]
registry = "git://mirrors.ustc.edu.cn/crates.io-index"
就使用了科大的镜像源,然后在终端中使用以下命令安装 Stork:
cargo install stork-search --locked
最后可以使用 stork --version
验证是否成功安装 Stork。
部署 Pelican Search
安装好 Stork 后的步骤就很简单了,在 Pelican 的 Python 环境中安装插件:
python -m pip install pelican-search
然后在 Pelican 设置中的 PLUGINS
引入 search
,在主题的模板文件(一般是 base.html
)中引入 Stork CSS 的 CDN(当然也可以改写后自己部署):
<link rel="stylesheet" href="https://files.stork-search.net/basic.css" />
以及 JavaScript:
<script src="https://files.stork-search.net/releases/v1.5.0/stork.js"></script>
<script>
stork.register("sitesearch", "{{ SITEURL }}/search-index.st")
</script>
最后就可以在设计的搜索区域通过以下方式调用 Stork 搜索了:
Search: <input data-stork="sitesearch" />
<div data-stork="sitesearch-output"></div>
Warning 以上 CSS 应在页面的头部,例如 <head>
中引入,而 JavaScript 则应在 <body>
的尾部引入。这是因为 HTML 文件是自上至下顺序执行的,如果加载 JavaScript 的位置靠前,比如在 <input data-stork="sitesearch" />
元素之前引入,在执行时该元素还未生成,就会找不到匹配的搜索框,提示没有 query selector `input[data-stork="sitesearch"]`
,导致 Uncaught StorkError
。
Pelican Search 的设置项
pelican-search 的设置项只有两项,一项 SEARCH_MODE
设定从 Markdown 文件建立索引还是从 HTML 建立索引,SEARCH_HTML_SELECTOR
可以用于指定从 HTML 的哪些内容中建立索引。但 Stork 的设置项不止这些,将其整合进 pelican-search 应该也不太难,留到以后有精力的时候尝试一下。
我浏览了一下 Stork 官方文档中的内容,发现了很多很有意思的东西。例如 minimum_indexed_substring_length
一项设置了建立索引的匹配项最短长度,默认值为 3,通俗来讲就是长于 3 的单词才会用于建立索引,那么在搜索时也需要起码键入 3 个字母才有结果。但这种做法对于中文来说就存在很大的问题,中文中最普遍的是双字词,所以文档中也提到 minimum_index_ideographic_substring_length
一项设置,默认值是 1,对于 CJK 字符而言,长于 1 的词就可以建立索引。可惜在我的试验中这个设置貌似并没有效果,在我使用汉字搜索时,也必须输入 3 个汉字才有结果,若要搜索双字词,只好用两个汉字加上空格的方法将就一下。除了这个问题之外就是使用中文搜索的精度不高,很难找到匹配项,所以 Stork 的最大不足其实就在于对中文的支持不好。据作者的消息,他也很希望能够提高 Stork 在中文搜索上的表现,可以期待一下后续的更新。
再来说说 Stork 的优点,那就是「快」。Stork 搜索的速度特别快,不论是汉字还是字母,击入三个字符秒出搜索结果,这一点的体验就特别好。另外 Stork 还支持包括英语在内的多种欧洲语言的词根检索,例如输入「get」,它亦能返回「getting」的检索结果,这个功能对于静态站点而言可谓强大。如果是英文语境下,Stork 搜索精度高、速度快、支持词根检索,简直是最为优雅的静态站点搜索插件,也期待一下后续它能否在中文搜索上也能提供如此流畅的体验。
Note 不知是我的原因还是 Stork 的问题,生成的索引文件巨大,足足有 16 MB,完全不能在网页上使用。于是我花了一整天的时间升级 Nginx 并配置上了 Brotli 压缩传输,压缩后只有大约 900 KB 了,加载速度大大提升。