本文记录 Hugo 的安装与部署入门笔记。
Hugo 安装
Hugo 是一个基于 Go 语言的静态网站生成工具(框架),特点是页面生成速度快,主题丰富,文档详细(英文)。
安装
1、到 Hugo Release 下载所需版本。推荐下载 Extended 版本,解压后应该得到 3 个文件,其中一个是 hugo.exe。
2、新建 D:\hugo\sites
作为 hugo 站点仓库,仓库可以存放多个站点。
3、新建 D:\hugo\bin
作为 hugo 执行目录,将前面解压得到的 hugo.exe 放到 bin 目录下。
4、将 D:\hugo\bin
加入到系统环境变量 Path
中,这样就可以通过 PowerShell 或 Git Bash 直接执行 hugo
命令。
验证安装是否成功:hugo help
,如果有 Hugo 的提示信息表明安装成功。hugo version
命令可以查看 hugo 版本。若提示未找到命令,则是环境变量未生效,需要寻求促使新增环境变量生效的方案(具体请求助搜索引擎)。
生成站点结构
使用 hugo new site
命令可以快速生成一个空的站点结构。假如希望在 D:\hugo\sites 目录下生成站点 migchar.com,则切换到 sites 目录下,执行:
$ hugo new site migchar.com
hugo 为我们生成的默认站点目录如下:
.
└── content
└── about
| └── _index.md // <- https://migchar.com/about/
├── post
| ├── _index.md // <- https://migchar.com/post/
| ├── firstpost.md // <- https://migchar.com/post/firstpost/
| ├── happy
| | └── ness.md // <- https://migchar.com/post/happy/ness/
| └── secondpost.md // <- https://migchar.com/post/secondpost/
└── quote
├── first.md // <- https://migchar.com/quote/first/
└── second.md // <- https://migchar.com/quote/second/
安装主题
Hugo 默认是没有主题的,需要先安装主题才能正常显示我们的网站内容。
# 切换到 migchar.com 站点根目录
$ cd migchar.com
# 下载主题到 themes 目录,更多主题到 hugo 官网下载
$ git submodule add https://github.com/budparr/gohugo-theme-ananke.git themes/ananke
一般情况下下载的主题都会带有 exampleSite 目录,这里面包含了主题需要的一些默认内容和结构,如果你希望自己的网站看起来跟主题预览显示的一样,可以将 exampleSite 目录里的内容复制到 站点根目录(migchar.com 目录),并根据需要修改 config.toml 文件。要使用哪个主题需要在 config.toml 里设置,也可以随时更换主题。
写作
content
在 migchar.com 目录下执行以下命令,就在 migchar.com/content/posts 下生成了文章。以后都在 content/ 下写作。推荐使用 Typora 编辑 md 文件。
hugo new posts/my-first-post.md
我们可以自己组织 content/ 目录,Hugo 会自动将我们自己组织的结构反映到生成的静态页面结构中。
.
└── content
└── about
| └── _index.md // <- https://migchar.com/about/
├── post
| ├── _index.md // <- https://migchar.com/post/
| ├── firstpost.md // <- https://migchar.com/post/firstpost/
| ├── happy
| | └── ness.md // <- https://migchar.com/post/happy/ness/
| └── secondpost.md // <- https://migchar.com/post/secondpost/
└── quote
├── first.md // <- https://migchar.com/quote/first/
└── second.md // <- https://migchar.com/quote/second/
front matter
对于一篇 Hugo 文章来说,front matter 的作用是告诉 Hugo 如何处理我们的文章。下面是一些可选的 front matter 属性:
---
title: "文章标题"
description: "文章的描述信息"
tags: [ "标签 1", "标签 2", "标签 3" ]
categories: [ "分类 1", "分类 2" ]
keywords: [ "Hugo", "keyword" ]
date: 2019-01-01
lastmod: 2019-01-02
# CJKLanguage: Chinese, Japanese, Korean
isCJKLanguage: true
# 如果 draft 为 true,除非使用 --buildDrafts 或 -D 参数,否则不会发布文章
draft: false
# 设置文章的过期时间,如果是已过期的文章则不会发布,除非使用 --buildExpired 或 -E 参数
expiryDate: 2020-01-01
# 设置文章的发布时间,如果是未来的时间则不会发布,除非使用 --buildFuture 或 -F 参数
publishDate: 2020-01-01
# 排序你的文章
weight: 40
# 使用这两个参数将会重置 permalink,默认使用文件名
url:
slug:
# 别名将通过重定向实现
aliases:
- 别名 1
- /posts/my-original-url/
- /2010/01/01/another-url.html
# type 与 layout 参数将会改变 Hugo 寻找该文章模板的顺序,将在下一节细述
type: review
layout: reviewarticle
# 三个比较复杂的参数
taxonomies:
linkTitle:
outputs:
# 实验性的参数
markup: "md"
# 你还可以自定义任何参数,这些参数可以在模板中使用
include_toc: true
show_comments: false
---
---
title: "文章标题"
description: "文章的描述信息"
tags: [ "标签 1", "标签 2", "标签 3" ]
categories: [ "分类 1", "分类 2" ]
keywords: [ "Hugo", "keyword" ]
date: 2019-01-01
lastmod: 2019-01-02
# CJKLanguage: Chinese, Japanese, Korean
isCJKLanguage: true
# 如果 draft 为 true,除非使用 --buildDrafts 或 -D 参数,否则不会发布文章
draft: false
# 设置文章的过期时间,如果是已过期的文章则不会发布,除非使用 --buildExpired 或 -E 参数
expiryDate: 2020-01-01
# 设置文章的发布时间,如果是未来的时间则不会发布,除非使用 --buildFuture 或 -F 参数
publishDate: 2020-01-01
# 排序你的文章
weight: 40
# 使用这两个参数将会重置 permalink,默认使用文件名
url:
slug:
# 别名将通过重定向实现
aliases:
- 别名 1
- /posts/my-original-url/
- /2010/01/01/another-url.html
# type 与 layout 参数将会改变 Hugo 寻找该文章模板的顺序,将在下一节细述
type: review
layout: reviewarticle
# 三个比较复杂的参数
taxonomies:
linkTitle:
outputs:
# 实验性的参数
markup: "md"
# 你还可以自定义任何参数,这些参数可以在模板中使用
include_toc: true
show_comments: false
---
运行与部署
1、启动 Hugo 内置服务器。
hugo server -D
通过本地 http://localhost:1313 就可以访问站点,每当站点内容有所修改时服务会实时编译并刷新浏览器,不需要每次修改都重启本地服务器。
2、生成静态页面
hugo
在站点根目录 migchar.com / 下执行 hugo
命令,默认会在站点根目录下生成 public 文件夹,里面是 hugo 生成的静态页面,只需要将 public/ 里的内容分发布到自己的服务器即可。如果要修改静态页面存放的目录,可以在 config.toml 里设置 publishdir
节点,或者使用 hugo /static-dir
命令指定静态页面生成路径。
如果一篇 md 文章在 fromt matter 设置了以下属性之一,则 hugo
命令不会编译这篇文章。
publishdate:
expirydate:
draft: true
写作流程
假设你已经熟悉前面的工作,以后当你要写新的文章时,大概的流程是这样子的:
1、在 content/posts/ 或其他你自定义的目录创建新文章。
hugo new posts/my-new-post.md
以上命令创建了默认 front matter 的文章,自动生成的 front matter 的取决于\hugo\sites\migchar.com\archetypes\default.md
,在我们执行 hugo new
的时候 Hugo 会使用 default.md 作为模板,如果你不希望每次生成的 md 文件默认 draft: true
,可以自己修改 default.md 文件。
# default content of default.md
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
# default content of default.md
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
2、启动内置 web 服务器,这样就可以在浏览器实时预览文章。如果不加上 -D 标识则 Hugo 不会编译标记为 draft 的文章。
hugo server -D
3、文章完成后运行 hugo 命令,生成静态页面,便于部署。
建议使用 hugo –minify 命令生成压缩的静态页面,减少页面体积
常用命令
用法: hugo hugo [flags] hugo [command] hugo [command] [flags] 可选的 Commands: config 打印站点配置信息 deploy 部署站点(前提是配置了部署信息) help 帮助信息 list 打印文章列表 new 为站点创建新的内容 server 一个高性能的 web 服务器 可选的 Flags: -b, --baseURL 指向服务器部署地址,部署必选,否则相关资源会 404,推荐在 config.toml 中指定 -D, --buildDrafts 包括被标记为 draft 的文章 -E, --buildExpired 包括已过期的文章 -F, --buildFuture 包括将在未来发布的文章
用法:
hugo
hugo [flags]
hugo [command]
hugo [command] [flags]
可选的 Commands:
config 打印站点配置信息
deploy 部署站点(前提是配置了部署信息)
help 帮助信息
list 打印文章列表
new 为站点创建新的内容
server 一个高性能的 web 服务器
可选的 Flags:
-b, --baseURL 指向服务器部署地址,部署必选,否则相关资源会 404,推荐在 config.toml 中指定
-D, --buildDrafts 包括被标记为 draft 的文章
-E, --buildExpired 包括已过期的文章
-F, --buildFuture 包括将在未来发布的文章
以下命令默认你已经切换到站点根目录 migchar.com/
# 例子 hugo new posts/my-post.md 在 content/posts/目录下创建文章 hugo 生成静态文件 hugo -D 生成静态文件,包括在 frontmatter 中 draft 为 true 的文章 hugo --minify 生成压缩的静态文件(html) hugo server -D 生成静态文件(包括 draft)并启动内置 web 服务器
参考文档:
在 Hugo 中使用 Sass – kok 的笔记本
https://wocai.de/post/2019/03/%E5%9C%A8-hugo-%E4%B8%AD%E4%BD%BF%E7%94%A8-sass/
支持编译 scss,必须使用 extended 版本。
sass-如何使用 Hugo 设置 SCSS-代码日志
https://stackoverflow.com/questions/54057291/how-to-setup-scss-with-hugo
部署到 Github Pages
通过 Github 客户端部署
前提:安装了 Git Bash(或 Github Desktop),拥有 Github 账号
Github 官方已经有详细的 Github Pages 教程:https://pages.github.com/。需要注意的是 Github Pages 有两种类型,一种是 User or organization site,一种是 Project site,这里我们选择创建 User site,方法是创建一个仓库命名为 username.github.io ,username 需要替换为 Github 账户名,然后将网页上传到这个仓库即可,通过 username.github.io 就可以访问上传的网页。hugo 官方有自动化部署的教程:https://gohugo.io/hosting-and-deployment/hosting-on-github/
我比较喜欢手动部署,以下介绍我的部署过程:
1、安装 Github 客户端:https://desktop.github.com/ ,登录 Github 账户。
2、通过客户端将 migchar/migchar.github.io 克隆到本地。
如果你的 public/ 是通过 hugo 命令生成的,那在 clone 之前需要先清空 public/ 文件夹中的内容。clone 完成后会在 public/ 中生成隐藏的 .git/ 文件夹,如果要保持这个 public/ 与你的 Github Pages 仓库相关联,便记得不要删除 .get/ 文件夹,如果误删,则要清空 public/ 后重新 clone 。
3、完成本地 public/ 与远程仓库 https://github.com/migchar/migchar.github.io 关联后,只要通过 hugo 命令在 public/ 生成静态页面,Github 客户端都能实时监测到文件的改动,手动在客户端点击 Commit to master 并 Push origin 就可以完成部署。访问 migchar.github.io 可以看到最新部署的博客。
绑定个人域名
前面的部署使得我们可以通过 migchar.github.io 访问本博客,但这是 github 提供的二级域名,如果想通过自己的个人域名 migchar.com 访问到 Github Pages,需要进行域名解析。
1 创建站点 CNAME
在本地 hugo 站点根目录(我的是 migchar/static/)新建 CNAME 文件,CNAME 文件里只写入你的域名(我写入了一行 migchar.com
),运行 hugo
命令重新生成 public/ 静态页面,commit 并 push 到 Github。这一步告诉 Github 我们要将这个 Pages 绑定到域名 migchar,而且任何 migchar.github.io 的访问将重定向到 migchar.com。也可以在 Github Pages 设置, 到 https://github.com/migchar/migchar.github.io/settings 设置页面找到 Github Pages 选项,将自己的域名填入 Custom domain 并保存,Github 会自动帮我们在站点根目录生成 CNAME 文件。
2 域名解析
到域名服务商进行域名解析,添加两条记录:
主机记录 | 记录类型 | 线路类型 | 记录值 |
---|---|---|---|
@ | A | 默认 | 185.199.110.153 |
www | CNAME | 默认 | yourusername.github.io |
其中 A 记录的记录值要填你 yourusername.github.io 站点对应的 IP 地址。注意这个 IP 值是 Github 提供的,在未来可能会改变,一旦改变就要重新解析。操作无误的话稍等一会就可以通过个人域名访问到 Github Pages 了。
开启 HTTPS
前两年 Github Pages 绑定个人域名后开启 HTTPS 比较麻烦,需要借助国外 Cloudflare 之类支持 SSL 的 CDN 服务才能完成,但是现在不用这么麻烦,因为 Github 已经与 Let’s Encrypt 合作,为自定义域名提供免费的 HTTPS 支持。
开启 HTTPS 很简单,到 https://github.com/migchar/migchar.github.io/settings 仓库设置页面找到 Github Pages 选项,如果 Enforce HTTPS 处于不可勾选状态,先清空 Custom domain 并保存,然后重新填入自定义域名再保存,最后勾选 Enforce HTTPS 选项即可。SSL 证书颁发需要一定时间,在证书生效之前访问自定义域名会提示证书问题,等生效就好了。如果证书生效后浏览器左侧还是提示不安全,需检查站点是否引用了 http 资源,替换成相应的 HTTPS 资源即可。
自动部署到云服务器
hugo 搭建个人博客-第三弹 Github Actions 自动部署到阿里云服务器 – 灰信网(软件开发博客聚合)
https://www.freesion.com/article/4704539398/
部署到 GAE
如果想要部署到 GAE,可以按照以下操作。个人觉得 GAE 没有 Github Pages 方便和灵活,但是 GAE 可以支持动态语言,也有够用的免费额度,根据需要取舍吧。
安装 Google Cloud SDK
下载并安装 Google Cloud SDK,根据安装程序提示完成安装。
确保勾选上 Bundles Python 和 Cloud Tools for PowerShell。安装完成后应该会自动启动 Google Cloud SDK Shell 并执行 gcloud init 命令, 我一般会将 d:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\bin
加入到系统的 Path 环境变量。
初始化 Google Cloud SDK
打开 cmd 或 PowerShell 执行 gcloud init 命令,进行初始化工作,根据指示登录 Google 账号、授权访问 Google Cloud Platform 资源、选择 Cloud Platform Project 等,还可以指定 网络代理。
gcloud 命令:
gcloud auth list
列出本地系统已有授权凭据的 Google 账号
gcloud config list
列出 gcloud sdk 的项目配置属性,包括 Google 账号,已授权 Cloud Platform Project 列表等。
配置代理:
gcloud config set proxy/type PROXY_TYPE gcloud config set proxy/address PROXY_IP_ADDRESS gcloud config set proxy/port PROXY_PORT
- Cloud SDK 支持以下
PROXY_TYPE
值:http
、http_no_tunnel
、socks4
、socks5
PROXY_IP_ADDRESS
是代理的访问位置的主机名或 IP 地址。PROXY_PORT
是代理运行时使用的端口(例如8080
)。
部署应用
假设我们已经在 Google Cloud Platform 创建了 My First Project 项目,并在该项目下创建了一个 App Engine 应用,接下来要做的便是把我们的项目代码部署到这个 App Engine 实例上。
在项目根目录创建 app.yaml 文件,PowerShell 或 CMD 切换到项目根目录(app.yaml 文件所在目录)执行以下命令:
gcloud app deploy
对于中国网络,执行部署命令前要求你已经设置好网络代理,让你的计算机能够访问到 Google 服务器。
如果设置了 Path 环境变量,部署命令也可以通过 Git bash 执行,要注意的是在 Git bash 中 gcloud 命令加上文件的扩展名,即:gcloud.cmd app deploy
部署完成后执行以下命令,可以通过浏览器访问应用,默认
gcloud app browse
配置 app.yaml
app.yaml 是 Google App Engine 的应用配置文件,主要作用是指定 url 与静态文件之间的对应关系,当然还包括与应用代码相关的信息,比如运行时和服务版本等。
app.yaml 位于服务程序的根目录。通常来讲 GAE 服务的目录如下:
my-service
app.yaml
public
index.html
...
我们希望访问 https://my-app-name.appspot.com 时对应的是 my-service/public/index.html 文件,同时访问其他 css、js 等静态文件时能自动对应上 public 中的文件。以下 app.yaml 能应付大多数情况。
runtime: python37
default_expiration: 1h
handlers:
- url: /(.*\.(appcache|manifest))
mime_type: text/cache-manifest
static_files: public/\1
upload: public/(.*\.(appcache|manifest))
expiration: "0m"
- url: /(.*\.atom)
mime_type: application/atom+xml
static_files: public/\1
upload: public/(.*\.atom)
expiration: "1h"
- url: /(.*\.crx)
mime_type: application/x-chrome-extension
static_files: public/\1
upload: public/(.*\.crx)
- url: /(.*\.css)
mime_type: text/css
static_files: public/\1
upload: public/(.*\.css)
- url: /(.*\.eot)
mime_type: application/vnd.ms-fontobject
static_files: public/\1
upload: public/(.*\.eot)
- url: /(.*\.htc)
mime_type: text/x-component
static_files: public/\1
upload: public/(.*\.htc)
- url: /(.*\.html)
mime_type: text/html
static_files: public/\1
upload: public/(.*\.html)
expiration: "1h"
- url: /(.*\.ico)
mime_type: image/x-icon
static_files: public/\1
upload: public/(.*\.ico)
expiration: "7d"
- url: /(.*\.js)
mime_type: text/javascript
static_files: public/\1
upload: public/(.*\.js)
- url: /(.*\.json)
mime_type: application/json
static_files: public/\1
upload: public/(.*\.json)
expiration: "1h"
- url: /(.*\.m4v)
mime_type: video/m4v
static_files: public/\1
upload: public/(.*\.m4v)
- url: /(.*\.mp4)
mime_type: video/mp4
static_files: public/\1
upload: public/(.*\.mp4)
- url: /(.*\.(ogg|oga))
mime_type: audio/ogg
static_files: public/\1
upload: public/(.*\.(ogg|oga))
- url: /(.*\.ogv)
mime_type: video/ogg
static_files: public/\1
upload: public/(.*\.ogv)
- url: /(.*\.otf)
mime_type: font/opentype
static_files: public/\1
upload: public/(.*\.otf)
- url: /(.*\.rss)
mime_type: application/rss+xml
static_files: public/\1
upload: public/(.*\.rss)
expiration: "1h"
- url: /(.*\.safariextz)
mime_type: application/octet-stream
static_files: public/\1
upload: public/(.*\.safariextz)
- url: /(.*\.(svg|svgz))
mime_type: images/svg+xml
static_files: public/\1
upload: public/(.*\.(svg|svgz))
- url: /(.*\.swf)
mime_type: application/x-shockwave-flash
static_files: public/\1
upload: public/(.*\.swf)
- url: /(.*\.ttf)
mime_type: font/truetype
static_files: public/\1
upload: public/(.*\.ttf)
- url: /(.*\.txt)
mime_type: text/plain
static_files: public/\1
upload: public/(.*\.txt)
- url: /(.*\.unity3d)
mime_type: application/vnd.unity
static_files: public/\1
upload: public/(.*\.unity3d)
- url: /(.*\.webm)
mime_type: video/webm
static_files: public/\1
upload: public/(.*\.webm)
- url: /(.*\.webp)
mime_type: image/webp
static_files: public/\1
upload: public/(.*\.webp)
- url: /(.*\.woff)
mime_type: application/x-font-woff
static_files: public/\1
upload: public/(.*\.woff)
- url: /(.*\.xml)
mime_type: application/xml
static_files: public/\1
upload: public/(.*\.xml)
expiration: "1h"
- url: /(.*\.xpi)
mime_type: application/x-xpinstall
static_files: public/\1
upload: public/(.*\.xpi)
# image files
- url: /(.*\.(bmp|gif|ico|jpeg|jpg|png))
static_files: public/\1
upload: public/(.*\.(bmp|gif|ico|jpeg|jpg|png))
# audio files
- url: /(.*\.(mid|midi|mp3|wav))
static_files: public/\1
upload: public/(.*\.(mid|midi|mp3|wav))
# windows files
- url: /(.*\.(doc|exe|ppt|rtf|xls))
static_files: public/\1
upload: public/(.*\.(doc|exe|ppt|rtf|xls))
# compressed files
- url: /(.*\.(bz2|gz|rar|tar|tgz|zip))
static_files: public/\1
upload: public/(.*\.(bz2|gz|rar|tar|tgz|zip))
# site root
- url: /
static_files: public/index.html
upload: public/index.html
expiration: "15m"
# index files
- url: /(.+)/
static_files: public/\1/index.html
upload: public/(.+)/index.html
expiration: "15m"
- url: /(.+)
static_files: public/\1/index.html
upload: public/(.+)/index.html
expiration: "15m"
- url: /(.*)
static_files: public/\1
upload: public/(.*)
需要注意的是 site root 跟 index files 的配置必须置于末尾。mime_type 描述文件的媒体类型,GAE 默认通过文件后缀来确认文件的 MIME 值。default_expiration 设置全局默认的浏览器缓存期限,expiration 为静态文件设置单独的浏览器缓存期限,GAE 在 Cache-Control 和 Expires HTTP 响应头中发送缓存期限。如果静态文件改动频繁,最好设置一个较短的缓存期限。缓存期限默认为 10min。
参考资料