个人网站迁移 Hugo 记


从 2018 年开始用 org-static-org 写博客到现在也有几年时间了,写的文章比较少,总体上这个简单的静态网站生成方案都能够满足需求。

但中途也发现一些不够用的地方,比如之前想要并贡献了一个生成 meta description 的 PR ,以便更好地在搜索引擎展示结果( SEO );又比如中途一度有区分中英双语博客的需求( index 列表、 RSS 等),但苦于没有想到很好的方法,就只能把两种文章都混杂在一起展示,用户体验不好。

/img/2021-07-10-org-static-blog-homepage.png
旧主页样式(可以看到链接带下划线,不利于阅读)
/img/2021-07-10-org-static-blog-post.png
旧博文样式

最近又有了一些其他的需求,就考虑做一个升级方案,大致需求有:

  1. 内置支持 orgmode

  2. 支持中英双语

  3. 较完善的 SEO 支持

  4. 较完善的社交分享功能

  5. 能集中展示个人的其他社交网站链接

  6. 除了博客之外,还能够展示其他的内容

  7. 界面稍微美观一点

详细分析需求之后,需要考虑的因素有:

- [X] 保持 blog, tags, rss 链接不变
  最重要的是 blog url 不能变,配置麻烦;最终决定 url 变了就变了,原来的 html 通过 meta refresh 来实现重定向解决。
- [X] SEO 功能验证
  - [X] robots.txt
  - [X] sitemap
  - [X] 支持 description ( front matter 已内置支持)
- [X] front matter 支持文章更新时间
  lastmod 字段
- [X] 社交分享效果验证
- [X] 选择一个合适的主题 theme
  需要支持的特性:
  - [X] 需要 responsive
  - [X] 多语言支持
  - [X] 展示 social links
  - [X] 社交分享支持
  - [X] 首页文章倒序,最新的在最上面
  - [X] 文章内部如何支持显示更新时间、其他语言版本?
    不支持
  - [X] 支持 toc 目录
    暂不支持,但可以接受: https://github.com/halogenica/beautifulhugo/issues/219
  - [X] 验证分页条数及效果
    默认 10 条

  综合考虑,最终选 beautifulhugo 。

根据 orgmode 官网 Blogs and Wikis with Org - orgmode.org 推荐,大致考察了几种方案:

  • Jekyll 不支持 orgmode ,仅支持 Markdown ;采用 Ruby 编写的,不太熟悉;

  • Hexo 不支持 orgmode ;采用 Node.js 编写,庞大的依赖让人望而却步;

  • Hugo 采用 Golang 编写,只有一个二进制文件,安装简单;另外构建极快;

最终决定采用 Hugo ,本以为很快能搞定,结果没想到要正确配置 Hugo 并没有那么简单。

迁移过程及遇到的问题

第一次使用没有经验,一开始按照官方文档 Quick Start | Hugo - gohugo.io ,先 hugo new site hello-world 创建一个项目来玩玩,然后修改主题 theme = "ananke" ,并新建一个 post 然后 hugo server -D 启动开发版 web server 。

到目前为止,整个过程都很顺滑,编译速度非常快,只要 100+ms ,很让人惊艳。

/img/2021-07-10-hugo-fast-build.png
编译只要 121ms ,非常快!

用 Git 保存好当前的 config.toml ,继续尝试。

然后按照文档指引,根据多语言的设置配置,结果发现 ananke 并不能很好地支持多语言(如果没记错的话,它不支持目录结构的多语言模式),于是不得不换别的主题尝试。

结果发现换一个主题之后,原来 ananke 主题下的 config.toml 在新主题下却不能工作了。

回顾整个过程,遇到的主要问题主要有2个:

  1. 多语言目录结构是怎样的?

  2. 如何调整一个主题的设置?

一开始以为 Hugo 主题只负责 UI 的渲染,与 Hugo 核心没有太多耦合的东西,一个 config.toml 就能够轻松适配多种不同的主题。结果在更换主题的过程中发现并不是这样的,而且我发现每一种主题一般都有一个样例配置 exampleSite/config.toml ,这才渐渐明白 Hugo 的配置其实是以主题配置为中心,从主题附带的示例配置出发进行微调,整个过程会顺利很多。

接下来主要说说多语言的目录结构问题。

多语言的目录结构

关于多语言的设置,文档有一页 Multilingual Mode | Hugo - gohugo.io 专门细说。主要有两种方式:

  1. 同一个文件夹下,以不同的文件名“后缀”表示比如的语言,比如 hello-hugo.en.md hello-hugo.zh-cn.md 分别表示同一篇文章的英文和中文版本。

  2. 通过不同文件夹来区分,比如一个 en 文件夹专门放英文文章,另外一个 zh-cn 专门放中文文章。 官方文档给出的示例是这样的:

    /content/english/about.md
    /content/french/about.md

我比较倾向于第二种方式,这样文件归类比较清晰明了。

但是,事与愿违,偏偏在选主题的过程中发现很多主题都能够支持第一种方式,但是不支持第二种方式。

而且要命的是,对于第二种方式的目录结构,文档也没有明确的说明,导致我一直没有弄明白正确的目录结构。

比如配置这样设置 contentDir :

[languages]
  [languages.en]
    contentDir = "content/en"
    languageName = "English"
    weight = 1
  [languages.zh-cn]
    contentDir = "content/zh-cn"
    languageName = "简体中文"
    weight = 2

最初我以为配置要求的目录结构是这样的:

content/
  posts/
    en/
    zh/

但通过摸索实践,最终发现它其实要求这样的:

content/
  en/
    posts/
  zh/
    posts/

这里发现的过程还挺有意思的,算是一种探索、发现新知识的手段。在经历了各种搜索都找不到结果,以及查看文档都始终不得要领的情况下,我就想,如何验证目录结构呢?

要不试试新建一篇文章,看它放在哪里了?

$ hugo new posts/test.org    
/path/to/hello-world/content/posts/en/posts/test.org created

通过琢磨这里新建文件的路径,我终于明白了多语言的目录结构,如上边所说,其实就是每种语言目录都是一个新的根目录,当时还特意发了一条推文宣布这个发现:

网站最终效果

经过对原来 org-static-blog 的 orgmode 源文件进行了一些微整,以及对 beautifulhugo 主题的修饰之后,终于生成了现在这个比较满意的效果。

对于 orgmode 源文件的调整,有以下微调:

  • date tags 这两个 front matter 格式调整

  • 图片路径更改

  • 博文的 URL 调整

    由于博客访问量并不大,我可以接受 URL 变更,同时对于原有的 html 通过 meta tag 来实现类似的 301 重定向,比如这样:

    <!DOCTYPE html>
    <html>
      <head>
        <meta http-equiv="refresh" content="0; url=/zh-cn/blog/2021-02-27-wrk-yuanli/">
      </head>
      <body>
        <p>The page has moved to:
          <a href="/zh-cn/blog/2021-02-27-wrk-yuanli/">here</a></p>
      </body>
    </html>

对于 beautifulhugo 主题,主要参考 Keep Coding - liujiacai.net 的网站进行了配色调整,更加便于阅读。(具体做法是,拷贝一份 beatifulhugo 仓库中的 main.css 到自己工程 static/css/main.css ,然后再进行调整)

遗留问题

虽然现在网站结果总体比较满意,但还存在一些小问题:

  1. 每一级 heading 使用编号,便于阅读

  2. beautifulhugo 页面性能较差,打开一个网页会发起 30+ 请求

    /img/2021-07-10-beautifulhugo-performance.png
    Lighthouse 测评结果表明性能较慢
  3. 本地预览版本也会启用 Google Analytics ,污染数据

    有两种解决方法:

    1. 维护两份配置,本地预览和部署版本通过 --config <xxx.toml> 来区分,也可以同时传入多个配置文件,通过 , 逗号隔开

    2. 以目录组织配置文件,通过命令行参数 --production 来指定环境;环境名就是 config/ 内的子目录名, _default/ 目录放兜底的全量配置。

      比如这样的目录结构:

      $ tree config/
      config/
      ├── _default
      │   └── config.toml   # 全量配置,不配置 GA id
      └── production
          └── config.toml   # 配置 GA id
      
      2 directories, 2 files

    第二种方法比较符合我的胃口,配置结构清晰,较为易用。有了上面的配置结构,通过 hugo server -D 启动的本地版本就不再上报 GA ;修改博客达到满意的效果之后,再 hugo --environment production 生成最终的包含 GA 的网站。

    参考:

  4. favicon 在 Chrome 浏览器中无法显示,在 Firefox 中正常(本地开发环境都 ok )

    可能是特定浏览器版本的原因,现在也 ok 了。

  5. footer 中的版权年份展示不对,按道理应该要展示到 2021 年 (突然又好了,不知道为何)

    文档说明在 https://gohugo.io/variables/site/

  6. figcaption (图题)样式的辨识读很差 (已解决)

Hugo 使用感受

Hugo 优点:很快,基本能满足我的大部分需求。

不足之处:

  1. 文档看起来很全,但是新手却很难快速地找到信息; 比如:

    • 多语言的目录结构

    • 配置文件参数有点乱,比如 [params] vs. [Params] 齐飞(第一个字母大小写无关?),比如 [Params] 参数存在的意义(或者说为何要定义这么一节配置)?

  2. 配置 config.toml 与主题强相关,换一个主题基本要重新配置,这点在文档中也没提到; 根据这几天的经验,我的最佳实践是,从选定主题的仓库中 copy 一个初始的 exampleSite 配置,然后再慢慢微调。

Hugo 不支持的 orgmode 特性

从目前遇到的情况看,发现不支持的 orgmode 特性有两个:


comments powered by Disqus