乐趣区

关于hugo:Hugo-之旅

之前写了篇文章《博客迁徙至 Hugo》,提了下应用 Typecho 多年后越发感触到运维的老本之高后,将博客迁徙到了动态博客程序 Hugo 下。应用 Vercel + Github 能够收费搭建高性能博客,绑定域名还能主动帮忙创立 SSL 证书。当然偷懒的话也能够间接应用默认调配的二级域名。

搭建

点击下面的按钮疾速到达创立页面,未登录的会须要登录,这块间接应用 Github 登录即可。登录后第一步会让你抉择 Vercel 账号,这里间接抉择 Personal Account 即可。之后会让你输出仓库名称,Vercel 会主动帮你创立并初始化该仓库。如果你的仓库不想让其它人看的话,这里能够勾选 Private Git Repository 创立公有仓库。

下一步这块会让你输出 Vercel 中我的项目的名称和一些配置。这里须要留神一下,官网提供的默认 Hugo 编译命令会把草稿文章也生成进去。须要在 BUILD COMMAND 那关上 OVERRIDE 按钮后输出 hugo --gc 进行笼罩。

稍等片刻之后,你就能够看到飘着满屏的彩带庆贺你创立博客胜利叻!点击 Visit 按钮你就能够看到你的博客的样子了。

因为是动态博客,你所有的文章都会存储在你方才新建的仓库中。你能够抉择将仓库下来批改后提交,也能够利用 Github 的在线编辑性能在线批改提交。提交之后 Vercel 会主动触发更新,从新构建并更新你的博客。

配置

默认每次提交 Vercel 构建实现之后都会把构建后的地址评论在你的 Github 提交下。你能够通过设置敞开该性能。另外默认 Vercel 指定的 Hugo 版本比拟老了,在 Markdown 编译过程中会产生一些异样的行为。咱们能够通过配置指定最新的 Hugo 版本进行编译。在我的项目根目录下新建 vercel.json 文件,并退出以下内容。

{
  "github": {"silent": true},
  "build": {
    "env": {"HUGO_VERSION": "0.78.1"}
  }
}

Hugo 博客自身的配置都在 config.toml 下。默认状况下 Hugo 生成的 URL 都是 /posts/hello-world/ 这种格局,不过之前做动静博客为了做伪动态,个别都将路由设置成了 /hello-world.html 这种格局。这种时候就须要在 config.toml 中减少 uglyurls 配置。

uglyurls = true
[permalinks]
  posts = ":slug"

前面的 permalinks 配置次要是用来去除文章的 /posts 前缀的。除此之外,默认的配置文章中的 HTML 是会被本义的,对于我这种偶然会在 Markdown 中写 HTML 的人来说操作有点多余。这时候能够在配置中定义它不本义。

[markup.goldmark.renderer]
  unsafe= true

域名

应用 Vercel 搭建的网站,它会默认提供一个 *.vercel.app 的二级域名,你能够间接应用这个域名拜访网站。如果你想要绑定本人的域名,也能够在后盾设置。进入网站后抉择本人的我的项目,抉择 SettingsDomains 进入域名配置界面,在输入框中增加本人的域名。它会提醒你须要给域名减少 A 记录或者是 CNAME 解析。依照提醒增加后后盾会自动检测是否失效。

失效的工夫视 DNS 服务器的失效工夫而定,我这边应用 DNSPod 还挺快的,大略 30 秒之内就失效了。失效后 Vercel 会主动帮咱们申请配置 SSL 证书,咱们全然不必操心证书的问题。期待片刻之后咱们就能间接应用新域名进行拜访了。

图片

默认所有的动态资源都放在 static/ 目录下。你能够将图片放在该目录下,例如 static/hello-world.jpg。在文章中则间接应用 /hello-world.jpg 地址援用即可。

因为 Github 仅有单文件小于 100M 的限度,Vercel 会将所有的资源部署到本人服务器上。所以应用仓库存储的形式会十分不便和平安,而且还不损失速度。惟一美中不足的是,因为是 HTTP 门路,在本地编写文章的时候会不不便。如果是应用 Typora 的话能够点击标签栏 格局 图像 设置图片根目录 将目录指定到 static/ 目录解决。VSCode 的话临时没有倒腾进去。

其实比拟好的计划是倡议大家创立一个文件夹,将该篇文章和它所用到的图片都归置到一块。应用相似组件化的思路治理内容,会更加不便后续的批改。

除了应用本地存储之外,你也能够抉择应用第三方的存储服务。收费服务的话能够试试 又拍云 提供的联盟打算,依照要求申请下即可。其余家的存储服务要么收费工夫无限,要么有局部免费性能。第三方存储的益处在于带有 CDN 减速,在速度上会很不便。但目前 Vercel 的速度我感觉还挺不错的,所以最终还是抉择了间接存仓库。

评论

应用动态博客之后,评论则只能抉择第三方评论零碎了。鉴于国情,国内的第三方评论服务都已有名无实。目前比拟出名的 Disqus , HyperComments 以及 来必力 都是国外的服务。HyperComments 是付费的服务就不多做探讨,Disqus 是老牌服务,提供了弱小的 API 对开发者较为敌对。来必力则是对国内用户敌对,集成了很多国内的社交账号登录。

除了专门提供评论的第三方服务之外,也有一部分是抉择自建评论服务。其中比拟出名的是 Valine 和 Gitalk 以及 Staticman,isso。Staticman 提供了弱小的 API 然而短少界面,isso 则是须要服务器部署,偏离了我应用动态博客的初衷就是不想保护服务器的目标,所以这两者都不多做探讨。Gitalk 是应用 Github issue 进行评论数据存储的评论脚本,适宜纯技术博客和极客应用。Valine 则是基于 LeanCloud Serverless 云存储进行评论数据存储的评论脚本,同时它还带有丑陋的外观,适宜各类人群应用。

博客站点上与评论相干的中央个别有三个中央:

  1. 首页显示最近评论
  2. 文章下显示以后文章评论数
  3. 文章底部显示该文章的评论列表以及输入框

最开始我抉择了 Disqus 作为本站的评论零碎。然而它有个问题国内失常无法访问。起初我发现 Hugo 的模板中是能够应用 getJSON 办法调取接口的。而 Vercel 的机器自身就在海内,那我实际上能够在博客编译阶段就获取到输出写到页面中。最近评论和评论数的显示还是比较简单的,而评论列表的显示则须要折腾一下了。不过 Disqus API 的应用频率是 1000 次 / 小时,当短时间部署频繁的话可能会有超过的危险。而且公布评论的接口没方法走该逻辑,还是须要一个代理服务。

最终让我决定不应用 Disqus 的起因是它的评论没方法让评论者输出网站地址,评论列表中的评论者昵称点击也无奈跳转到用户输出的网站中。这对于有着大量的老式评论数据的我来说是不太能承受的。所以基于这些种种原因,我最初又将评论迁徙到了 Valine 下。

我对 Valine 的次要问题在于两点:

  1. 早前应用 Valine 的时候发现了大量的 XSS 破绽
  2. 荒野无灯大大反馈的“泄露用户隐衷问题”

以上两个是十分重要的平安问题,不过我看 XSS 的问题作者曾经修复,实际上对用户输出的所有 HTML 内容进行本义能够躲避该问题。而灯大反馈的 IP 泄露的问题,作者也通过不记录 IP 来躲避该问题。这两个问题造成的起因其实还是因为 Serverless。因为我想间接在编译的时候将相干数据动态化,所以我势必是须要减少一个服务端来帮我进行接口的封装,最初也能躲避这些问题。

不过 Valine 不知因为什么起因不开放源码,只在 Github 提供编译后代码,这点除了让我比拟无语之外,革新工作也比较慢。原本我只须要将它 UI 中调用 LeanCloud API 的逻辑替换成我的接口逻辑即可。然而因为没有源码,只能本人从新制作 UI 了。

更新:基于 Valine 衍生的带后端评论零碎曾经实现 https://github.com/lizheming/… 已切换至该评论零碎。2020/11/08

搜寻

短少服务端之后,动态博客的搜寻性能也无奈本人实现。目前比拟出名的是第三方搜寻服务 Agolia,提供了收费的文章索引和搜寻的性能。除了应用第三方服务之外,还发现有一种比较简单的做法就是将所有数据生成到一个文件中,前端下载该文件进行搜寻后果展现。这里头比拟出名的是 fuse,它是一个 JS 模块,将输出传入之后它能帮咱们疾速的匹配到命中后果。

目前本站应用的是后一种办法,该办法的长处是不依赖第三方服务,本人就能实现搜寻性能。毛病是第一次搜寻的时候须要下载残缺的数据,对文章比拟多的网站用户鸭梨会比拟大。应用第二种办法第一步是须要先创立全量的数据索引,通过以下配置告知 Hugo 编译时创立 index.json 索引文件。

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

当然咱们还须要为新的数据编写生成的模板文件,在 layouts/ 下减少 index.json 文件,并退出以下内容:

{{- $.Scratch.Add "index" slice -}}
{{- range .Site.RegularPages -}}
    {{- $.Scratch.Add "index" (dict "title" .Title "contents" .Plain  "summary" .Summary "permalink" .Permalink "date" (.Date.Format "2006 年 01 月 02 日")) -}}
{{- end -}}
{{- $.Scratch.Get "index" | jsonify -}}

其中 dict后的字典能够增加多个字段,视你 JS 渲染脚本中须要的字段而定。实现这些之后 Hugo 编译就会生成 index.json 文件了。

最初咱们须要减少一个搜寻页面,该页面会先加载 index.json 而后应用 fuse 进行数据查找,最初渲染成 HTML 输入搜寻后果。具体的代码能够间接查看源码 https://imnerd.org/search.htm… 参考本站的搜寻页。

// 以下为示例代码
let fuse;
async function search(text) {if(!fuse) {const indexData = await fetch('/index.json', {method: 'GET'}).then(resp => resp.json());
    fuse = new Fuse(indexData, {...});
  }
  const result = fuse.search(text);
  renderHTML(result, '#app');
}

其它

Hugo 动态博客能提供给咱们施展的空间十分多,比如说我参考 屈屈的博客 减少了一个博客文章公布 >180 天的话,就在文章详情页黄条揭示:

揭示:本文最初更新于 313 天前,文中所形容的信息可能已产生扭转,请审慎应用。

失常来说因为我没有服务端,所以只能应用前端来计算以后工夫与公布工夫的时间差。但其实转念一想,编译时也是能够拿到时间差的,只是这个时间差无奈随着工夫的变动而变动。不过我只有每天编译一次,就能解决变动的问题了。在 Vercel 我的项目 SettingsGitDeploy Hooks 中你能够输出 Hook 名称和触发分支创立一个 Hook URL。只有拜访该 URL 就能够触发 Vercel 更新博客。

{{if eq .Type "posts" -}}
    {{$ageDays := div (sub now.Unix .Date.Unix) 86400 }}
    {{if gt $ageDays 180}}
        <p class="expired-tips"> 揭示:本文最初更新于 &nbsp;{{$ageDays}}&nbsp; 天前,文中所形容的信息可能已产生扭转,请审慎应用。</p>
    {{end}}
{{end}}

而在 Vercel 的 Marketplace 中,有一个 EasyCron 的服务提供了定时工作的性能。我在下面设置了每天零点拜访 Hook URL 触发博客更新,就这样解决每天须要更新工夫的问题。

另外屈屈博客中的“查看本文 Markdown 版本”也是个不错的性能,在 Hugo 中也能够实现,实质是在编译的时候顺便生成一份 .md 的 Markdown 文件即可。

首先咱们须要在 layouts/ 下减少 single.md 文件,示意的是当文章页(Single)须要导出 .md 的数据的时候应用该模板。模板内容不必填写,为空即可。而后在 config.toml 中新增 .md 文件类型,并告知 Hugo 文章须要减少编译 Markdown 文件类型。

[mediaTypes]
  [mediaTypes."text/plain"]
    suffixes = ["md"]

[outputFormats.MarkDown]
  mediaType = "text/plain"
  isPlainText = true
  isHTML = false

[outputs]
  page = ["HTML", "MarkDown"]
退出移动版