目录

个人博客的诞生

前前后后花了超过一个月的时间进行调研、选型、测试,终于上线了目前的这个版本,最终基于hugo搭建,主题为loveit的静态博客,评论系统使用基于leancloud的valine,搜索引擎采用algolia,发布在cloudflare的pages上面,下面简要讲解一下

一开始的思路是使用cloudflare的worker搭建个人博客,参考链接如下

https://github.com/Arronlong/cfblog-plus

https://blog.gezhong.vip/article/009000/update-log.html

https://github.com/gdtool/cloudflare-workers-blog

http://blog.arrontg.cf/article/000006/.html

当时尝试的时候只有基础版本,虽然功能已经很强大了,但是不支持搜索功能,评论系统的引入也比较硬,另外虽然worker的免费版本调用数量足够高,但还是有限制,而且主题模板太少了,感觉像是半成品,最后就没有采用。另外如果是运行在worker上的,除了KV的限制,还不支持上传图片,所有图片只能采用链接插入,我还专门找教程做了一个简易的图床,参考链接如下:

https://wlnxing.com/archives/49.html

https://mitsea.medium.com/backblaze-b2-cloudflare-%E6%90%AD%E5%BB%BA%E5%9B%BE%E5%BA%8A-94afa1f762dc

只能说cf的worker真的是强大。。。但是放博客图片每次都要做成链接也不是特别便捷(而且我用cf pages也无限流量)

最后用的方案就是现在看到的样子,这里放一下参考链接,详细配置细节后面展开

使用hugo的loveit主题:

https://hugoloveit.com/zh-cn/

https://bore.vip/archives/hugo-theme-LoveIt/

https://lewky.cn/posts/hugo-3.html/

https://www.ethanzhang.xyz/%E9%AB%98%E8%B4%A8%E9%87%8Floveit%E4%B8%BB%E9%A2%98-%E9%9D%99%E6%80%81hugo%E5%B9%B3%E5%8F%B0-nginx%E8%87%AA%E5%8A%A8%E5%8F%91%E5%B8%83-%E8%85%BE%E8%AE%AF%E5%85%8D%E8%B4%B9tls%E8%AF%81%E4%B9%A6%E7%9A%84%E9%83%A8%E7%BD%B2%E6%95%99%E7%A8%8B/

使用的搜索引擎的教程:

https://edward852.github.io/post/hugo%E6%B7%BB%E5%8A%A0algolia%E6%90%9C%E7%B4%A2%E6%94%AF%E6%8C%81/

评论系统方面参考:

http://www.dlwxz.com/2020/07/hugo%E5%8D%9A%E5%AE%A2loveit%E4%B8%BB%E9%A2%98valine%E8%AF%84%E8%AE%BA%E7%B3%BB%E7%BB%9F%E9%85%8D%E7%BD%AE/

hugo
Hugo

在github上下载hugo,找个地方解压缩后配置到PATH中(我是win)环境

找了一个教程做参考,主要git命令如下

hugo new site my_website
cd my_website

设置主题,主题可以通过github搜索“hugo theme”并按star排序来参考热度

git init
git clone https://github.com/dillonzq/LoveIt.git themes/LoveIt
baseURL = "/"
# [en, zh-cn, fr, ...] 设置默认的语言
defaultContentLanguage = "zh-cn"
# 网站语言, 仅在这里 CN 大写
languageCode = "zh-CN"
# 是否包括中日韩文字
hasCJKLanguage = true
# 网站标题
title = "我的全新 Hugo 网站"

# 更改使用 Hugo 构建网站时使用的默认主题
theme = "LoveIt"

[params]
  # LoveIt 主题版本
  version = "0.2.X"

[menu]
  [[menu.main]]
    identifier = "posts"
    # 你可以在名称 (允许 HTML 格式) 之前添加其他信息, 例如图标
    pre = ""
    # 你可以在名称 (允许 HTML 格式) 之后添加其他信息, 例如图标
    post = ""
    name = "文章"
    url = "/posts/"
    # 当你将鼠标悬停在此菜单链接上时, 将显示的标题
    title = ""
    weight = 1
  [[menu.main]]
    identifier = "tags"
    pre = ""
    post = ""
    name = "标签"
    url = "/tags/"
    title = ""
    weight = 2
  [[menu.main]]
    identifier = "categories"
    pre = ""
    post = ""
    name = "分类"
    url = "/categories/"
    title = ""
    weight = 3

# Hugo 解析文档的配置
[markup]
  # 语法高亮设置 (https://gohugo.io/content-management/syntax-highlighting)
  [markup.highlight]
    # false 是必要的设置 (https://github.com/dillonzq/LoveIt/issues/158)
    noClasses = false
hugo new posts/个人博客的诞生.md

完成后编辑个人博客的诞生.md的内容,将draft调整为false,标签和分类也直接写,并在其中编辑内容,示例如下:

title: "个人博客的诞生"
date: 2021-03-15T18:35:13+08:00
draft: false
tags: ["hugo", "blog", "cloudflare"]
categories: ["基础教程"]
featuredImage: "/images/个人博客的诞生/title.jpg"
featuredImagePreview: "/images/个人博客的诞生/title.jpg"
description: "简要描述了你所看到的博客是如何从0-1诞生的"
typora-root-url: ..\..\static

置顶<!--more-->同时撰写description,或直接撰写summary,都可单独展示摘要,不配置默认为前70个字符

另外可以在利用 https://realfavicongenerator.net/ 生成网站图标并解压缩后放置到/static路径下,图片可以统一放在/static/images路径下

编辑器推荐Typora,注意如果本地编辑器使用了Typora撰写markdown,需要在"格式"-“图像"下拉框中选定"设置图片根目录"并设置到/static路径,这样才能自动渲染显示图片

使用命令启用本地预览,注意实时编辑会改变预览输出

# 本地预览
hugo server
# 添加draft的预览
hugo server -D
# 自定义端口测试
hugo server -p=1234
# 开启评论系统、cdn等
hugo server -e production

主要参考这个教程,图片效果如下(测了几次,某些情况下加载速度好像会稍微慢一点,不够好在也不用自建服务器):

ml_map
机器学习用例

可以考虑用在单图片超过25M的时候使用,而且有防火墙防盗链配置整体效果还是不错的,当然受限于网络状况也有可能图片加载不出来,链接独立还不方便cdn反代,

另外涉及到图片压缩的话,实测tinypng效果还不错

hugo不仅仅支持基础语法,还可以通过shortcodes支持大量拓展功能,具体可以参考以下链接:

略过域名注册和dns解析等,直接来看cloudflare的pages的教程 ,也可以选择别的(github pages / Netlify等),主要考虑到cf的抗cc能力太强了,而且除了单文件大小上限25M外几乎没有限制,

注意需要在pages中的“设置”-“环境变量”下添加“HUGO_VERSION” = “0.81.0”(使用的版本)不然默认会使用较老的版本导致部署失败,建议同时设置“PYTHON_VERSION” = “3.7”,便于后续融合python脚本(如果本地编译则不需要设置cf pages的环境变量)

主要参考教程是来自:

https://10101.io/2019/04/17/encrypt-content-in-hugo

使用了hugo_encryptor这个开源项目,大概效果如下:

文章的部分内容被密码保护:

密码是“PASSWORD”,考虑更新及时性还可以另外写个脚本部署的时候update一下依赖的py文件和html模板

cf关联github后会自动检测并部署,但融合加密后使用cf的远端编译总是不成功,后面考虑到本地python环境齐全,索性改成本地编译完后推送public到cf发布,并将cf中“构建与部署”中的“构建目录”留空,推送github前运行deploy.sh文件,再hugo server可以预览编译后的站点

实测lunr太慢,algolia还行,algolia注册记得选香港会更快,除了配置[params.search],还需要配置index,主要参考了以下教程的内容:

https://edward852.github.io/post/hugo%E6%B7%BB%E5%8A%A0algolia%E6%90%9C%E7%B4%A2%E6%94%AF%E6%8C%81/

记得在config.toml配置文件中添加:

# 配置 Algolia index
[outputs]
  home = ["HTML", "RSS", "Algolia"]

[outputFormats.Algolia]
  baseName = "algolia"
  isPlainText = true
  mediaType = "application/json"
  notAlternative = true

[params.algolia]
  appId = "xxx"
  indexName = "xxx"
  searchOnlyKey = "xxx"

根目录下 layouts/_default (没有就新建) 文件夹中新建 list.algolia.json 文件,内容如下:

{{/* 生成Algolia搜索索引文件 */}}
{{- $.Scratch.Add "index" slice -}}
{{/* content/posts或content/post目录下的博文才生成索引 */}}
{{- range where (where .Site.Pages "Type" "in" (slice "posts" "post")) "IsPage" true -}}
  {{- if and (not .Draft) (not .Params.private) -}}
    {{- $.Scratch.Add "index" (dict "objectID" .File.UniqueID "url" .Permalink "content" (.Summary | plainify) "tags" .Params.Tags "lvl0" .Title "lvl1" .Params.Categories "lvl2" "摘要") -}}
  {{- end -}}
{{- end -}}
{{- $.Scratch.Get "index" | jsonify -}}

另外还需要用到npm的atomic-algolia包来自动上传,创建.env环境,npm run algolia可以放到deploy.sh里面发布时同步执行,需要注意如果algolia过了试用期需要重新登录选一下free套餐,不然搜索不到内容,整体是够用的

评论系统本来想用gitalk,登录不上的时候还折腾了一下用cf的worker自建cors跨域代理api,但最终因为不支持github的private仓库,最后放弃转用valine国际版来配置(需要手机号验证),主要配置照着模板写就行了,参考如下:

  [params.page]
    rssFullText = false
    lightgallery = true

    [params.page.comment]
      enable = true
      [params.page.comment.valine]
        enable = true
        appId = "xxx"
        appKey = "xxx"
        placeholder = ""
        avatar = "mp"
        meta= ""
        pageSize = 10
        lang = ""
        visitor = true
        recordIP = true
        highlight = true
        enableQQ = false
        # serverURLs = "https://leancloud.hugoloveit.com"
        # emoji 数据文件名称, 默认是 "google.yml"
        # ("apple.yml", "google.yml", "facebook.yml", "twitter.yml")
        # 位于 "themes/LoveIt/assets/data/emoji/" 目录
        # 可以在你的项目下相同路径存放你自己的数据文件:
        # "assets/data/emoji/"
        emoji = ""

需要注意web安全域名,如果支持多站点同步登录需要配置多条域名,另外创建两个对象“Counter”和“Comment”,别的会自动生效,整体免费可用项参考这里,个人博客搓搓有余了,然后评论系统的邮件通知提醒可以参考这个项目,直接在leancloud上使用云引擎运行,测试了一下163和QQ邮箱都可以按预期执行

另外如果涉及到leancloud的流量控制,可以参考这篇文章,

https://duter2016.github.io/2020/06/09/%E8%A7%A3%E5%86%B3LeanCLoud%E5%AE%9A%E6%97%B6%E5%94%A4%E9%86%92%E5%A4%B1%E8%B4%A5%E7%9A%84%E6%B5%81%E6%8E%A7%E9%97%AE%E9%A2%98/

使用github action/各大厂商云函数/cloudflare worker脚本定时访问来避免leancloud休眠

更新
一段时间后,考虑到数据安全性和功能性,最后把评论系统切换到了Twikoo,中间还试用了Waline,感觉也还行

hugo对视频支持也还算可以,不过放不了本地视频,经过一番搜索,我开始准备直接用gif,但是实测后发现gif不仅没声音而且不能暂停,相同内容比mp4体积还大很多,体验不是很好,

后面找到三种关于本地视频播放的教程,第一种是来自:

https://blog.233so.com/2020/04/hugo-loveit-with-dplayer-supported/

https://blog.233so.com/2020/04/hugo-loveit-with-more-video-share-shortcodes-supported/

这位大神直接硬改loveit主题的源代码插入了dplayer的播放器支持,另外还有支持多种网站视频加载,第二种是来自:

https://dev.to/aakatev/add-a-video-to-your-hugo-website-104

比之前简单一点但还是需要引入一堆资源,第三种是学习了以下信息得到,

https://github.com/gevhaz/hugo-theme-notrack/search?q=video-shortcode

https://github.com/martignoni/hugo-video

在根目录创建layouts\shortcodes\html-video.html,写入:

<style>
.video-shortcode {
  width: 100%;
  height: auto;
  padding: 1em 0;
}
</style>
<video class="video-shortcode" poster="{{ .Get "poster" }}"  {{ if ne (.Get "controls") "false" }}controls {{ end }}preload="none" {{ if eq (.Get "autoplay") "true" }}autoplay {{ end }}{{ if eq (.Get "loop") "true" }}loop {{ end }}{{ if eq (.Get "muted") "true" }}muted {{ end }}playsinline>
    <source src="{{ .Get "src" }}" type="{{ .Get "type" }}">
    There should have been a video here but your browser does not seem
    to support it.
</video>

然后在博客中直接使用<html-video src="https://xxxx.mp4" poster="xxx.jpg" type="video/mp4">,视频来自第一篇教程那个大神的博客,整体效果如下:

另外最后第一个大神的方案我也简化实现了,全部代码就放一个html,根目录创建layouts\shortcodes\video.html,代码如下:

<style>
.dplayer {
  position: relative;
  width: 100%;
  height: auto;
  margin: 3% auto;
  text-align: center;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest/dist/hls.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/flv.js@latest/dist/flv.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dplayer@latest/dist/DPlayer.min.js"></script>

<div id="{{ .Get `id` }}"></div>
<script>
  function loadDPlayer(){
    let dp = new DPlayer({
      container: document.getElementById({{ .Get `id` }}),
      autoplay: {{ .Get `autoplay` | default false }},
      theme: {{ .Get `theme` | default `#b7daff` }},
      loop: {{ .Get `loop` | default false }},
      lang: {{ .Get `lang` | default `zh-cn` }},
      screenshot: {{ .Get `screenshot` | default true }},
      hotkey: {{ .Get `hotkey` | default true }},
      preload: {{ .Get `preload` | default `none` }},
      logo: {{ .Get `logo` }},
      volume: {{ .Get `volume` | default 0.7 }},
      mutex: {{ .Get `mutex` | default true }},
      video: {
          url: {{ .Get `url` }},
          pic: {{ .Get `pic` }},
          thumbnails: {{ .Get `thumbnails` }},
          type: {{ .Get `type` | default `auto` }},
      },
      subtitle: {
          url: {{ .Get `sub` }},
          type: {{ .Get `subtype` | default `webvtt` }},
          fontSize: {{ .Get `fontsize` | default `20px` }},
          bottom: {{ .Get `bottom` | default `10%` }},
          color: {{ .Get `color` | default `#b7daff` }},
      },
    });
  }
  document.addEventListener('DOMContentLoaded', loadDPlayer, !1);
</script>

dplay的这个难度在于要支持cors,调用方式<video id="highline" url="http://xxx.mp4" pic="xxxxx.jpg">,整体效果相当不错,放个clappr的视频http://clappr.io/highline.mp4纪念一下研究了好久最终没有用的第二个方案吧。。。

dplay一般涉及的参数如下:

参数名默认值描述
id必须播放器父元素唯一 id,用于处理同页面多个播放器,同页面不可重复
url必须视频直链地址
pic可选视频封面图片
thumbnails可选视频缩略图,可以使用 DPlayer-thumbnails 生成
type可选,“auto”流媒体类型,可选值: ‘auto’, ‘hls’, ‘flv’, ‘dash’, ‘webtorrent’, ‘normal’ 或其他自定义类型, 见#MSE 支持
autoplay可选,false视频自动播放
theme可选,"#b7daff”主题色
loop可选,false视频循环播放
lang可选,“zh-cn”播放器显示语言,可选值: ‘en’, ‘zh-cn’, ‘zh-tw’
screenshot可选,true开启截图,如果开启,视频和视频封面需要允许跨域
hotkey可选,true开启热键,支持快进、快退、音量控制、播放暂停
preload可选,“metadata”视频预加载,可选值: ‘none’, ‘metadata’, ‘auto’
logo可选在左上角展示一个 logo,你可以通过 CSS 调整它的大小和位置
volume可选,0.7默认音量,请注意播放器会记忆用户设置,用户手动设置音量后默认音量即失效
mutex可选,true互斥,阻止多个播放器同时播放,当前播放器播放时暂停其他播放器
sub可选字幕链接
subtype可选,“webvtt”字幕类型,可选值: ‘webvtt’, ‘ass’,目前只支持 webvtt
fontsize可选,“20px”字幕字号
bottom可选,“10%”字幕距离播放器底部的距离,取值形如: ‘10px’ ‘10%’
color可选,"#b7daff”字幕颜色

视频这一部分足足花了四五天的时间来进行试错选型和debug优化等工作,第一个bug是我的下载器Neat Download Manager下载的js文件不全导致第一次前几个依赖js的方案全部起不来,第二个bug特别奇怪是cf的缓存导致本地mp4视频在safari上播放不起来,最后参考了这个讨论里面的方案改成自建网盘url链接并修改了nginx的配置使用cf反代网盘文件,第三个bug是dplay要启用cors,

解决第二个bug的时候尝试了自建网盘出链接引发了第三个bug&mldr;&mldr;最后试用了多个基于cf反代的商业网盘并精挑细选了一个方案才最终解决所有bug,生产方案是来自这个项目,就是配置真的是异常复杂,而且代码还有bug默认不支持cors。。。找了好久学习了官方样例才解决cors的问题,

这一部分真是非常不容易,虽然这样的实现还是需要有个vps来自建网盘,并不是原先预计的全serverless博客这种调用url的实现方式需要自建vps或者用某个网盘直链或者反代网盘,都有一定的门槛和技术难度,花了好久才勉强维持serverless博客的初衷,唯一的限制是cf的worker有调用量限制,不过正常一般都是够用的,要是哪天不够用我这blog应该已经非常火了。。。那就到时候买一个付费的worker续上就行,另外记得进行cf的防盗链设置有助于缓解调用量的问题

更新
后来好像没那个bug了,直接mp4上传播放就行了,注意大小不要超过25M