Back
Featured image of post 全新全新的布鲁喔尔格!

全新全新的布鲁喔尔格!

采用 Vercel 构建的 Hugo 站点

这两天把实习给辞了(祝垃圾人早日破产)学习压力太大就会什么都想搞把博客还有一些框架给重整了一下。按照惯例写一下整理记录,主要介绍一下一些坑,整理思路与最近上手的好用的小玩具工具。

0. Never use submodule

上一个 Hugo 的主题使用的是Diary

导入到 blog 的时候用的是 git submodule….于是在这几天的改造中一不小心 git fetch 了一下,自定义的部分都消失了…

自定义的地方有

  • Caption shortcode(已弃用,我放在了优先级更高的根目录,所以没有受到影响)
  • 文章插图尺寸与位置快速调整方法,已经忘记是如何实现的了,可以参考这篇文章
  • 其他的自定义 CSS…

得到的教训就是,不要用 submodule,把 .git 给删了!!

1. 配置 Hugo

一些有用的小配置,发挥 Hugo 框架本身的生产力。

Raw Html

Hugo 默认的 Markdown 渲染器是会把 html 直接过滤,这样我们想实现的一些效果就无法正常展示。

config.toml 下加入字段即可

[markup.goldmark.renderer]
    unsafe= true        # render raw html

渲染 emoji

😂 🐈 🐻 👧 👯‍♀️

enableEmoji = "true"      # enable emoji

开启后在 markdown 写作时就可以使用形如 :balabala: 的 emoji shortcode,或者直接输入 emoji 到 markdown

构建时忽略

ignoreFiles = [ "\\.ig$"] # ingore files when generate*

这个设定会让 Hugo 在 generate 的时候忽略所有后缀为 ig 的文件/目录,我常用这个来存放原图到文章目录下,便于整理的同时又不会重复生成不必要的文件。

Google Analytics

Hugo 提供了一个内部模版(Internal Templates)方法,方便用户无须二次重写一些常用的模板代码。我在这里用的是 Google Analytics,后文会讲到。

config.toml 中:

googleAnalytics = "Google Analytics的UAID"

2. 迁移思路

原本站点托管的 VPS 现在每个月要多 charge 我 5🔪,一气之下我决定使用静态页面托管服务。

先来研究一下旧站点存在的问题

  1. 导火索:评论系统无法正常工作,leancloud 测试实例拒绝 self-wake
  2. 文章页插图不美观
  3. 视觉疲劳,旧主题不想再改造了
  4. 评论系统 Valine 自成一体太特殊,不便控制
  5. Valine 运行在 leancloud 上,不再支持免费的 24h 的运行实例了

新的博客在解决旧问题的基础上首先一个满足的是更舒服的阅读体验,其次是保证加载速度。

鲁迅说,舍得舍得,有舍有得。为了无痛迁移,必须舍弃一些东西,比如 Valine 内的评论(我看看了看没有很多,但是都是nostalgia回忆啊)

主题轮子大挑选

找了半天开源主题,一来二去Stack居然都解决了美观舒适和评论系统的问题。

评论系统方案

最佳的实践应该是自己写一套评论系统。

  1. 原先的 Valine 老了,Leancloud 不支持免费的 24h 实例,固放弃。

  2. Disqus 在国内死无葬身之地,考虑到读者体验还是不采用。

  3. Github Issue 便于管理,可控性好,安装快,最后看中Utterances,配置十分简单,这里不多赘述。

Follow-ups

  • 实现 wordpress 式的免登录评论系统
  • 提取 Issues 的评论 meta,导入到自建评论系统中(可控性)
  • 用户验证与反垃圾(Akismet)
  • 两套数据库方案 SQL 和 NoSQL

3. 大迁移

新旧主题之间的目录结构很不一样,需要手动修改包括 frontmatter,config 在内的大量内容。

Bootstrap 部分引入

旧的文章中有用到部分 Bootstrap 的组件,完整引入 Bootstrap 的话影响网站速度同时会造成样式冲突。

先去官网下载所需版本的 sass 文件后解压,我们需要的样式文件和脚本文件都在 bootstrap-sass-3.3.7/assets

需要引入的组件:button, badge, label, animation

样式引入

动效有些地方涉及到脚本,我们先导入样式文件。

新建 _bootstrap.scss 到样式目录

// Partial import bootstrap components
// Theme Color is included in "bootstrap/variables"
@import 'bootstrap/variables';
@import 'bootstrap/mixins';
@import 'bootstrap/component-animations';
@import 'bootstrap/buttons';
@import 'bootstrap/button-groups';
@import 'bootstrap/badges';
@import 'bootstrap/labels';

在样式目录下新建 bootstrap 目录,导入这四个样式文件(夹)(e.g. _variables.scss)

然后引入到与 _bootstrap.scss 同级目录下的 layout 的 css 中,我在这里就不详细说明目录结构了。

@import 'bootstrap.scss';

但这个 bootstrap 的 sass 有坑,没有包含 outline buttons 的样式,所以我们还得加一个

@import 'bootstrap/outline_buttons';

_bootstrap.scss 里,这是 _outline_buttons.scss

// Credit to https://gist.github.com/tkawa/50d1cb8049a0e210ba91fcb06698e89e
// Backports from Bootstrap 4
@mixin button-outline-variant($color, $color-hover: #fff) {
  color: $color;
  background-image: none;
  background-color: white; // transparent is better?
  border-color: $color;

  &:hover {
    color: $color-hover;
    background-color: $color;
    border-color: $color;
  }

  &:focus,
  &.focus {
    color: $color-hover;
    background-color: $color;
    border-color: $color;
  }

  &:active,
  &.active,
  .open > &.dropdown-toggle {
    color: $color-hover;
    background-color: $color;
    border-color: $color;

    &:hover,
    &:focus,
    &.focus {
      color: $color-hover;
      background-color: darken($color, 17%);
      border-color: darken($color, 25%);
    }
  }

  &.disabled,
  &:disabled {
    &:focus,
    &.focus {
      border-color: lighten($color, 20%);
    }
    &:hover {
      border-color: lighten($color, 20%);
    }
  }
}

// Remove all backgrounds
.btn-outline-primary {
  @include button-outline-variant($btn-primary-bg);
}
//.btn-outline-secondary {
//  @include button-outline-variant($btn-secondary-border);
//}
.btn-outline-info {
  @include button-outline-variant($btn-info-bg);
}
.btn-outline-success {
  @include button-outline-variant($btn-success-bg);
}
.btn-outline-warning {
  @include button-outline-variant($btn-warning-bg);
}
.btn-outline-danger {
  @include button-outline-variant($btn-danger-bg);
}

脚本引入

collapse 和 button 需要脚本的加持才有动画显示,我们要在存放 ts 的目录下放入 button.tscollapse.ts,然后在修改入口 ts 文件,加入

import './button'
import './collapse'

大功告成!

添加 Google Analytics

Hugo 提供了 Internal Templates 方便用户使用,譬如 Google Analytics

config.toml 里提供一个 Google Analytics 的 UA 代码

googleAnalytics = "Google Analytics的UAID"

在 layout 里添加 templates 到 head

{{ if .Site.GoogleAnalytics }} {{ template "_internal/google_analytics.html" . }} {{ end }}

4. 发布: Vercel

本地构建完成后就可以正式发布了。除去 VPS 方案,primitive thoughts 是采用 GitHub Pages,但是考虑到国内访问速度不佳。Google 得到一些解决方案。

Google 加速 ghpages 的结果
Google 加速 ghpages 的结果

有些教程提到使用 Netlify 这样的 Serverless 服务来对 ghpages 加速,那为什么不直接用他们来构建 hugo 呢!

我的方案是和 Netlify 类似的 Vercel(步骤过于简单,不再赘述):

  1. 将 hugo 的根目录上传至 github
  2. 新建一个 Vercel 账户,添加你的 git 仓库。
  3. 发布项目

在根目录下新建 vercel.json 补充配置:

{
  "build": {
    "env": {
      "HUGO_VERSION": "0.76.3"
    }
  },
  "routes": [{ "handle": "filesystem" }, { "src": "/(.*)", "status": 404, "dest": "/404.html" }]
}

规定了 hugo 的版本号,并禁止了 vercel 的文件系统1

对项目设置稍加调整,覆盖默认的 command, clean cache and minify pages.

 

Vercel 会对监控你的仓库,只要有新的 commit 被 push,vercel 就会随后 build 一个新的实例,免去了手动 build 的烦恼,实现了CI/CD(持续集成/持续交付)。之前在 VPS 上我曾考虑过用 Onedrive 实时同步(过于麻烦,可控性差),最后写了一个很蹩脚的shell 脚本来应付。

另外就是加上 Cloudflare 的 CDN,但效果实际上好像还不如不开 CDN 呢…(CF 就是传说中的减速)

5. 迁移之后

尽量多写作。

好玩的玩具

最近很喜欢用 Notion 记笔记/写日记,Notion 支持 Markdown+个人无限存储空间,个人很喜欢这种 blocks philosophy 构建 articles or pages。一开始看了网上的一些介绍教程(以少数派为主的)后以为会很难上手,学习成本高,但实际上我在创建账号打开那些范例模版的时候就已经体会到 Notion 是怎么样的一个模式了,我很喜欢它譬如 embedded page 这样好玩的 features,还可以导出多种格式(markdown, pdf, doc 等)。Notion 来构建个人的知识库是不二的选择。

emmmmmm 好像也没有其他好玩的玩具了,pls, Surge yyds, 感恩 my friends @FlickerSoul

To-do

  • Dplayer add-on (福州遊記这篇文章中有一个视频无法正常播放)
  • floating TOC (table of contents)
  • redirect visitors depending on their geoip especially for mainland visitors (to speed up)
  • short-status publish (hugo templating)
  • top posts (posts sticking on the top)
  • search
  • right hand side widgets
  • webp images
  • back to top
  • some features in my mind

有想到的再来补充吧!(都做完了再来更新)

Rufus Scrimgeour, Harry Potter and the Order of the Phoenix
Rufus Scrimgeour, Harry Potter and the Order of the Phoenix

“To Harry James Potter,” he read, and Harry’s insides contracted with a sudden excitement, “I leave the Snitch he caught in his first Quidditch match at Hogwarts, as a reminder of the rewards of perseverance and skill.”

— Rufus Scrimgeour, Harry Potter and the Order of the Phoenix


  1. Directory Listing ↩︎