博客迁移之路 从hexo换成hugo

简介

由于之前使用的 hexo 搭建的博客,但是很多资源都是使用的国外 cdn,静态资源有点多,在国内使用有点慢,而且我的博客是小水管,所以物色好久才发现 hugo 这个静态博客生成工具,试用之后发现比较满足我目前的要求,而且主题也不少,博客迁移的工作量也不大,最重要一点是 go 实现的,配上 go 实现的 caddy,所以综合考虑,我的技术选型如下:

  • traefik (完美与 docker 结合)
  • hugo
  • caddy

文章主要包含下面几部分:

  • 软件介绍
  • 环境搭建
  • 博客初始化
  • 博客部署

软件介绍

Hugo是一个强大的静态博客生成器,由spf13使用Golang开发。在性能和生成文章的速度上都不错。

Caddy同样也是一个由Golang开发的HTTP server,其最大的亮点就是内建了HTTPS和HTTP2的支持,同时自动能够向Let’s Encrypt申请证书。同时,支持Middleware的功能,使用Golang撰写的Middleware能够支持各种各样的功能,同时任何人都可以撰写自己的Middleware,个性化这个HTTP Server。

环境搭建

  • golang 环境搭建
  • hugo 安装

golang环境搭建

Go语言中文网 下载 golang 的安装包,然后按照 安装说明 进行安装,基本都是下一步即可。

安装完成后,校验安装是否成功:

$ go version
go version go1.14.4 windows/amd64

我这里安装的是 golang 的 1.14.4 版本。

hugo 安装

在命令行终端安装 github.com/spf13/hugo 工具:

$ go get -v github.com/spf13/hugo

校验安装是否成功:

$ hugo version
Hugo Static Site Generator v0.73.0 windows/amd64 BuildDate: unknown

安装成功,版本是 v0.73.0

博客初始化

  • hugo 初始化博客项目
  • 使用 hugo 主题 pure
  • 从 hexo 迁移到 hugo

hugo 初始化项目

使用Hugo快速生成站点,比如希望生成到 /path/to/site 路径:

$ hugo new site /path/to/site

这样就在 /path/to/site 目录里生成了初始站点,进去目录:

$ cd /path/to/site

初始化成功后项目结构:

▸ archetypes/
▸ content/
▸ layouts/
▸ static/
config.toml

使用 hugo 主题 pure

皮肤列表 挑选一个心仪的皮肤,比如你觉得 Hyde 皮肤不错,找到相关的 GitHub 地址,创建目录 themes,在 themes 目录里把皮肤 git clone 下来:

本博客中使用的 pure 主题:

# 创建 themes 目录
$ cd themes
$ git clone https://github.com/xiaoheiAh/hugo-theme-pure pure

pure 配置:

baseURL: https://example.com/
theme: pure
title: Pure theme for Hugo
defaultContentLanguage: en  # en/zh/...
footnoteReturnLinkContents: ↩
hasCJKLanguage: true
paginate: 7
enableEmoji: true
PygmentsCodeFences: false
googleAnalytics: ""      # UA-XXXXXXXX-X 
permalinks:
  posts: /:year/:month/:filename/

taxonomies:
    category : categories
    tag : tags
    series : series
outputFormats:          # use for search. recommend not to modify 
  SearchIndex:
    mediaType: "application/json"
    baseName: "searchindex"
    isPlainText: true
    notAlternative: true

outputs:
    home: ["HTML","RSS","SearchIndex"]  # recommend not to modify
# sitemap
sitemap:
  changefreq: monthly
  filename: sitemap.xml
  priority: 0.5

menu:
  main:
    - identifier: home
      name: Home
      title: Home
      url: /
      weight: 1

    - identifier: archives
      name: Archives
      title: Archives
      url: /posts/
      weight: 2

    - identifier: categories
      name: Categories
      title: Categories
      url: /categories/
      weight: 3

    - identifier: tags
      name: Tags
      title: Tags
      url: /tags/
      weight: 4

    - identifier: about
      name: About
      title: About
      url: /about/
      weight: 5


params:
  since: 2017
  dateFormatToUse: "2006-01-02"
  enablePostCopyright: true
  # the directory under content folder that you want to render
  mainSections: ["posts"]
  # Enable/Disable menu icons
  # Icon Reference: http://blog.cofess.com/hexo-theme-pure/iconfont/demo_fontclass.html
  enableMathJax: true #Enable mathjax support, to use mathematical notations
  highlightjs:
    langs: ["python", "javascript"] # refer to http://staticfile.org/, search highlight.js, already have highlight.min.js

  # Allows you to specify an override stylesheet
  # put custom.css in $hugo_root_dir/static/
  # customCSS: css/custom.css

  menuIcons:
    enable: true  # 是否启用导航菜单图标
    home: icon-home-fill
    archives: icon-archives-fill
    categories: icon-folder
    tags: icon-tags
    repository: icon-project
    books: icon-book-fill
    links: icon-friendship
    about: icon-cup-fill

  # profile
  profile:
    enabled: true # Whether to show profile bar
    avatar: avatar.png
    gravatar: # Gravatar email address, if you enable Gravatar, your avatar config will be overriden
    author: xiaoheiAh
    author_title: author title
    author_description: Good Good Study, Day Day Up~
    location: Shanghai, China
    follow: https://github.com/xiaoheiAh
    # Social Links
    social:
      links:
        github: https://github.com/xiaoheiAh
        # weibo: http://weibo.com/{yourid}
        # twitter: https://twitter.com/
        # facebook: /
        rss: /index.xml
      link_tooltip: false # enable the social link tooltip, options: true, false
  # Site
  site:
    logo:
      enabled: true
      width: 40
      height: 40
      url: favicon.ico
    title: Hugo # 页面title
    favicon: favicon.ico
    board: <p>enjoy~</p> # 公告牌

  # Share
  # weibo,qq,qzone,wechat,tencent,douban,diandian,facebook,twitter,google,linkedin
  share:
    enable: true # 是否启用分享
    sites: weibo,qq,wechat,facebook,twitter # PC端显示的分享图标
    mobile_sites: weibo,qq,qzone # 移动端显示的分享图标

  # Comment
  comment:
    type:  # type disqus/gitalk/valine 启用哪种评论系统
    disqus: your_disqus_name # enter disqus shortname here
    gitalk: # gitalk. https://gitalk.github.io/
      owner: #必须. GitHub repository 所有者,可以是个人或者组织。
      admin: #必须. GitHub repository 的所有者和合作者 (对这个 repository 有写权限的用户)。
      repo:  #必须. GitHub repository.
      ClientID: #必须. GitHub Application Client ID.
      ClientSecret: #必须. GitHub Application Client Secret.
    valine: # Valine. https://valine.js.org
      appid: # your leancloud application appid
      appkey: # your leancloud application appkey
      notify: # mail notifier , https://github.com/xCss/Valine/wiki
      verify: # Verification code
      placeholder: enjoy~ # comment box placeholder
      avatar: mm # gravatar style
      meta: nick,mail # custom comment header
      pageSize: 10 # pagination size
      visitor: false # Article reading statistic https://valine.js.org/visitor.html

  # Donate
  donate:
    enable: false
    # 微信打赏
    wechatpay:
      qrcode: donate/wechatpayimg.png
      title: 微信支付
    # 支付宝打赏
    alipay:
      qrcode: donate/alipayimg.png
      title: 支付宝

  # PV
  pv:
    busuanzi:
      enable: false # 不蒜子统计
    leancloud:
      enable: false # leancloud统计
      app_id: # leancloud <AppID>
      app_key: # leancloud <AppKey>

  # wordcount
  postCount:
    enable: true
    wordcount: true # 文章字数统计
    min2read: true # read time 阅读时长预计

  # config
  config:
    skin: theme-black # theme color default is white. other type [theme-black,theme-blue,theme-green,theme-purple]
    layout: main-center # main-left main-center main-right
    excerpt_link: Read More
    toc: true

  # Sidebar
  sidebar: right

  # Search
  search:
    enable: true # enable search. thanks for https://raw.githubusercontent.com/ppoffice/hexo-theme-icarus/master/source/js/insight.js

  # Sidebar only the following widgets. you can remove any you don't like it.
  widgets:
    - board
    - category
    - tag
    - recent_posts

可以根据自己的需要进行修改。

运行并测试:

hugo server --buildDrafts

从 hexo 迁移到 hugo

把 hexo 博客中的 blog/source/_posts/ 中的文章复制到 hugo 目录下 content/posts 中即可

运行并测试:

hugo server --buildDrafts

博客部署

博客部署使用的 docker,因为博客需要进行打包,所以这里使用的是 docker 的多阶段打包:

使用 caddy 作为文件服务器

Caddyfile:

:80 {
    root * /var/www/blog
    file_server browse
}

Dockerfile:

FROM klakegg/hugo:alpine as builder

WORKDIR /var/www

COPY . /var/www/

RUN cd /var/www && hugo

FROM caddy:alpine

RUN rm -rf /var/www/blog/*

# 使用了多阶段构建
COPY --from=builder /var/www/public /var/www/blog
COPY ./Caddyfile /var/www/blog/Caddyfile

WORKDIR /var/www

CMD caddy run --config /var/www/blog/Caddyfile

docker-compose.yml

version: "3"

networks:
  default:
    external:
      name: traefik_gateway

services: 
  blog:
    build: . 
    restart: always
    tty: true
    labels: 
      # 设置Host 为 www.sockstack.cn 进行域名访问
      - "traefik.http.routers.blog.rule=Host(`www.sockstack.cn`)" # traefik 绑定域名
      - "traefik.http.routers.blog.tls=true" # 启用https
      - "traefik.http.routers.blog.tls.certresolver=le" # 证书生成器
      - "traefik.http.routers.blog.entrypoints=https" # entrypoints 简单理解就是端口转发
      - "traefik.http.middlewares.test-compress.compress=true" # 使用 gzip 压缩,有一定的规则,满足规则就会使用 gzip压缩
      - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" # 限流
      - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=50" # 限流

启动博客:

$ docker-compose up -d

访问 www.sockstack.cn 测试成功。