使用Hugo搭建静态站点

虽然前一篇Blog宣称自己要用Markdown开始写Post,但实际操作起来还是发现了诸多不兼容问题(插件与主题间、插件与插件间的),让编写和修改文章变得十分繁琐,于是我研究了一下静态Web站点生成工具Hugo。Hugo是由前Docker的重量级员工(2015年8月末从Docker离职):Steve Francia实现的一个开源静态站点生成工具框架,类似于JekyllOctopressHexo,都是将特定格式(最常见的是Markdown格式)的文本文件转换为静态html文件而生成一个静态站点,多用于个人Blog站点、项目文档(Docker的官方manual Site就是用Hugo生成的)、初创公司站点等。这类工具越来越多的受到程序员等颇具“极客”精神的群体的欢迎,结合github.com等版本控制服务,采用具有简单语法格式但强大表达力的Markdown标记语言,人们可以在很短时间内就构建出一个符合自己需求的静态Web站点。在这些工具中,Hugo算是后起之秀了,它最大的优点就是Fast! 一个中等规模的站点在几分之一秒内就可以生成出来。其次是良好的跨平台特性、配置简单、使用方便等。这一切均源于其良好的基因:采用Go语言实现。Steve Francia除了Hugo平台自身外,还维护了一个Hugo Theme的Repo,这个Hugo主题库可以帮助Hugo使用者快速找到自己心仪的主题并快速搭建起静态站点。目前国内使用Hugo的人还不多,但感觉其趋势是在逐渐增多。这里写下这篇Post,也算是为大家入个门,引个路吧。

一、安装Hugo

Hugo托管在github.com上,因此获取Hugo很方面,目前有至少两种方法可以安装Hugo。

1、安装包

对于普通用户(无git、无开发经验)而言,直接下载安装包是最简单的方式。我们可以下载Hugo的Release版,截至目前为止最新版本是v0.14,可以在这里下载你的平台(支持linux, windows, darwin, netbsd, freebsd和arm等)对应的版本。不过我发现0.14版本似乎有Bug,在我的MacOsX上生成Hugo Docs站点总是panic。

2、源码编译

对于开发者而言,源码编译是最Geek的方式:

go get -u -v github.com/spf13/hugo
go build -o hugo main.go
mv hugo $GOPATH/bin

在命令行下执行hugo命令,如果得到类似下面结果,则说明你已经成功安装了Hugo:

$hugo version
Hugo Static Site Generator v0.15-DEV BuildDate: 2015-09-20T23:53:39+08:00

二、生成静态站点

1、创建静态站点

我们来创建一个名为”tonybai.com”的静态站点:

$hugo new site tonybai.com
$tree
.
└── tonybai.com
    ├── archetypes
    ├── config.toml
    ├── content
    ├── data
    ├── layouts
    └── static

我们看到,通过hugo new site命令,我们建立了tonybai.com站点的后台目录结构。但细心的你会发现:这里的目录都是空的。除了config.toml中可怜的三行内容:

baseurl = "http://replace-this-with-your-hugo-site.com/"
languageCode = "en-us"
title = "My New Hugo Site"

不过即便目录为空,这也是一个完整的静态站点源文件,我们可以基于这些文件生成我们的站点。

$cd tonybai.com
$hugo server

0 draft content
0 future content
0 pages created
0 paginator pages created
0 tags created
0 categories created
in 6 ms
Serving pages from /Users/tony/test/hugotest/tonybai.com/public
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop

上面的hugo命令在将repo转换为静态Site文件放入public目录:

├── public
│   ├── 404.html
│   ├── index.html
│   ├── index.xml
│   └── sitemap.xml

之后Hugo启动了一个server作为该Site的Web Server。通过浏览器访问http://localhost:1313,你将看到一个完全空白的站点首页。虽然这个站点没啥实用价值(一片空白),但这却是一个良好的起点。

2、添加Theme

添加了Theme后的站点才有血有肉,丰富多彩。

添加Theme的步骤如下,我们以Hyde Theme为例:

首先创建themes目录,并下载Hyde Theme文件:

$ mkdir themes
$ cd themes
$ git clone https://github.com/spf13/hyde.git

接下来,我们需要对Site进行一些配置,tonybai.com/config.toml是Site的顶层配置文件,配置后的config.toml文件如下:

baseurl = "http://tonybai.com/"
languageCode = "en-us"
title = "Tony Bai"
theme = "hyde"

[params]
    description = "这里是Tony Bai的个人博客"
    themeColor = "theme-base-08" # for hyde theme

其中:
theme = “hyde” 指定站点使用Hyde主题;
themeColor = “theme-base-08″ 指定了站点的主题颜色(默认是黑色的,这里改成一种红色)

在tonybai.com目录下重新执行hugo server,并打开浏览器查看站点首页,你会发现视野里有内容了:

站点截图1

3、第一个Post

结构和样式有了,我们还没有内容。我们来创建站点的第一个Post:

$hugo new welcome.md
/Users/tony/Test/hugotest/tonybai.com/content/welcome.md created

hugo在content下创建welcome.md文件,我们编写一些文件内容:

+++
Categories = ["Development", "GoLang"]
Description = ""
Tags = ["Development", "golang"]
date = "2015-09-23T16:30:37+08:00"
menu = "main"
title = "你好,Hugo"

+++

这是使用Hugo创建的站点中的第一篇文章。

保存后,重新执行hugo server命令,打开浏览器,你将看到下面的情形:

站点截图2

至此,如果你是极简主义者,你对其他没有任何要求,你就可以用这个站点写Post了。

三、调试与部署站点

1、调试站点

采用Hugo的静态站点在编辑文章、调试站点时十分方便,你要做的就是编辑文本,保存后,打开浏览器看渲染后的结果。不过反复执行hugo server命令还是有些烦,hugo早想到了这一点,hugo提供了:
-w, --watch[=false]

执行hugo server命令时加上-w选项,hugo就可以自动检测本地站点文件的变更,并自动执行md -> html转换。这样刷新浏览器页面就可以看到你修改后的结果了:

$hugo server -w
0 draft content
0 future content
1 pages created
0 paginator pages created
2 tags created
2 categories created
in 16 ms
Watching for changes in /Users/tony/test/hugotest/tonybai.com/{data,content,layouts,static,themes/hyde}
Serving pages from /Users/tony/test/hugotest/tonybai.com/public
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop

通过hugo server -w的输出日志来看,hugo可以自动检测data,content,layouts,static,themes/hyde目录下的变更,但站点顶层config.toml的改动无法被检测,还需要重启hugo server。

2、部署站点

和Jekyll类似,使用hugo的静态站点可以部署到github page中,不过这里不详细描述这种方法,可以看官方文档

如果是在vps下部署,那么hugo转换后的public文件夹可以被直接用于部署到像nginx、apache、caddy这样的Web Server下面。

当然hugo本身也可以作为一个Web server来支撑你的静态站点,就像上面提到的,你可以在你的站点目录(比如上面的”tonybai.com”)下执行:

$sudo hugo server --bind="0.0.0.0" -v -w -p 80 -b http://tonybai.com

如果无法使用80端口(比如通过apache2反向代理),那么需要加上–appendPort=false,否则转换后的public下面的url地址都会带上你的hugo端口(1313):

$hugo server -v -w -p 1313 -b http://tonybai.com --appendPort=false

四、配置和维护站点

大多数人不会止步于上面那个仅仅能写Post的站点,配置分类、标签;修改字体样式;添加评论功能;增加统计代码;增加代码高亮(程序员最爱);甚至定制主题是Geek们最喜欢折腾的事情,这里无法全表,列举几个常见的配置和维护方法,还是已hyde主题为例。

1、配置分类、标签

在浏览器中输入:http://localhost:1313/categories/或http://localhost:1313/tags,你会看到站点输出了一个类似目录列表似的页面:

development/
golang/

development和golang从何而来呢?

隐藏得再深,也要给它揪出来:

tonybai.com/themes/hyde/archetypes/default.md

+++
Description = ""
Tags = ["Development", "golang"]
Categories = ["Development", "GoLang"]
menu = "main"
+++

由于我们使用了hyde theme,所以我们只需看themes/hyde下面的目录结构即可,tonybai.com下面的除content之外的其他layout, data等可忽略不计。在hyde/archetypes下存放着这个主题下文章的默认分类和tags集合。这个default的作用是每次new post后,hugo会将default中的tags和categories自动copy到Post头中的tags和categories中。

每个Post的分类和tag在post自身的.md文件头中指定,见Categories和Tags两个配置项:

tonybai.com/content/welcome.md

+++
Categories = ["Development", "GoLang"]
Description = ""
Tags = ["Development", "golang"]
date = "2015-09-23T16:30:37+08:00"
menu = "main"
title = "你好,Hugo"

+++

你可以根据需要在你的post md文件中灵活增删你的tags和categories,不局限于default.md中的那些已知项。

2、修改字体样式

hyde主题的字体样式在tonybai.com/themes/hyde/layouts/partials/head.html中指定:

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=PT+Sans:400,400italic,700|Abril+Fatface">

由于googleapis在国内无法访问,因此要么注释掉这行(使用浏览器默认字体样式),要么将其换为其他字体公共服务,比如:

<link rel="stylesheet" href="http://fonts.useso.com/css?family=PT+Sans:400,400italic,700|Abril+Fatface">

字体的设置在tonybai.com/themes/hyde/static/css下的各个css文件中,谨慎调整。

3、添加评论功能

Hugo没有内置评论功能,要增加评论功能需要集成第三方评论服务,比如国外最流行的Disqus。hyde主题内置了disqus评论插件,不过需要你按如下操作配置一下,否则页面下方的disqus插件总是显示无法连接。

获取disqusShortname

这里用disqus主账号不行,需要用主账号login后:add a newsite to disqus,比如加入tonybaicom.disqus.com,这样你的disqusShortname就为:tonybaicom;

配置disqusShortname

在tonybai.com/config.toml中配置disqusShortname:

[params]
    disqusShortname = "tonybaicom"

如果你要使用国内的评论服务,比如:多说,你可以参考tonybai.com/themes/hyde/layouts/partials/disqus.html,用多说提供的install code替换disqus的code,形成duoshuo.html:

<!-- 多说评论框 start -->
<div class="ds-thread" data-thread-key="{{ .URL }}" data-title="{{ .Title }}" data-url="{{ .Permalink }}"></div>
<!-- 多说评论框 end -->

<!-- 多说公共JS代码 start (一个网页只需插入一次) -->
<script type="text/javascript">
    var duoshuoQuery = {short_name:"{{.Site.Params.duoshuoShortname}}"};

    (function() {
     var ds = document.createElement('script');
     ds.type = 'text/javascript';ds.async = true;
     ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js';
     ds.charset = 'UTF-8';
     (document.getElementsByTagName('head')[0]
      || document.getElementsByTagName('body')[0]).appendChild(ds);
     })();
    </script>
<!-- 多说公共JS代码 end -->

再在tonybai.com/themes/hyde/layouts/_default/single.html中替换下面的代码:

{{ if and (isset .Site.Params "disqusShortname") (ne .Site.Params.disqusShortname "") }}
                <h2>Comments</h2>
                {{ partial "disqus" . }}
            {{ end }}

为类似下面的代码:

{{ if and (isset .Site.Params "duoshuoShortname") (ne .Site.Params.duoshuoShortname"") }}
                <h2>Comments</h2>
                {{ partial "duoshuo" . }}
            {{ end }}

注意:一旦用上面多说代码,config.toml中就需要配置duoshuoShortname了:

[params]
    duoshuoShortname = "tonybaicom"

4、代码高亮

Hugo官方说明中采用Pygments来进行代码高亮的支持,在部署机上安装Pygments,个人觉得这个方法不好。于是换另一外一种js代码法,即采用highlightjs的方法支持代码高亮。

highlightjs同样很强大,支持135种语言(关键是支持Golang)和60多种样式(有我喜爱的github样式和monokai_sublime样式),但不支持linenumber。

我们首先将highlightjs下载到本地:

tonybai.com/themes/hyde/static/css/highlight.js/8.8.0/styles/github.min.css
tonybai.com/themes/hyde/static/js/highlight.js/8.8.0/highlight.min.js

然后在tonybai.com/themes/hyde/layouts/partials/head.html添加如下代码:

    <!-- Highlight.js and css -->
    <script src="{{ .Site.BaseURL }}js/highlight.js/8.8.0/highlight.min.js"></script>
    <link rel="stylesheet" href="{{ .Site.BaseURL }}css/highlight.js/8.8.0/styles/github.min.css">
    <script>hljs.initHighlightingOnLoad();</script>

highlightjs会自动检测语言类型,并使用github样式。

5、统计代码

提供统计服务的站点,比如statcounter.com一般都会提供安装代码(js)的,将那段代码copy到tonybai.com/themes/hyde/layouts/partials/head.html中即可。

四、进阶

1、index.html、single.html和list.html

站点的首页模板在themes/hyde/layouts/index.html中。除首页外,其他Post或叫Page,都被Hugo抽象为两类:单体页面和列表页面,对应这两种页面的默认模板都在themes/hyde/layouts/_default中,分别对应着single.html和list.html。

我们之前通过hugo new welcome.md创建的Post使用的是single.html模板,而查看tags或categories的页面默认采用的是list.html,比如查看tonybai.com/categories/golang,你会在浏览器中看到分类在golang这一类的所有Post列表。

2、type和section

我们执行如下两个命令:

$hugo new post/firstpost.md
tonybai.com/content/post/firstpost.md created
$hugo new post/secondpost.md
tonybai.com/content/post/secondpost.md created

创建后我们可以看到站点的源文件结构变成了:

... ...
├── archetypes
├── config.toml
├── content
│   ├── post
│   │   ├── firstpost.md
│   │   └── secondpost.md
│   └── welcome.md
... ...

hugo中源码文件的布局影响着最终生成的html文件的结构布局。有些时候我们的站点可能会分成若干个部分,每部分通过目录隔离开,比如这里content下的post目录,这样hugo转换后,firstpost.html和secondpost.html也会在public的post目录下。这里的“post”被称为一个section。

hugo会为每个section自动生成index.html页,采用的是index.html模板。

至于是否采用的是hyde/layouts/_default下的list.html,这要看host的匹配order,官方给出的是:

/layouts/section/SECTION.html
/layouts/_default/section.html
/layouts/_default/list.html
/themes/THEME/layouts/section/SECTION.html
/themes/THEME/layouts/_default/section.html
/themes/THEME/layouts/_default/list.html

这个例子中THEME=hyde, SECTION=post

在本例子中,/layouts/下是空的,不予考虑。/themes/hyde/layouts下没有建立section/post.html模板,/themes/hyde/layouts/_default/section.html也不存在,因此用的是_default/list.html。

hugo官方建议静态站点源码文件按section组织,每个section使用相应(同名)的type,这样section下面的.md就会自动使用响应type的meta data。

当我们hugo new post/firstpost.md时,hugo会到archetypes下找是否有post.md文件,如果有则使用post.md文件的categories和tags来初始化content/post/firstpost.md的元数据,如果没有post.md,则使用archetypes/default.md的。

3、模板语言

Hugo使用Golang的模板语法,表达能力很强大;配合Hugo predefined的变量或自定义变量,你可以玩转模板。关于模板内容较多,这里不赘述,需要时查看官方详细的manual

开始使用Markdown写Blog

近期发了一些带有大量代码的Go技术文章,结果文章中的代码样式被大家鄙视了,比如评论中的“不忍直视”、“这代码看得让人难受”等。于是我决定花些时间尝试做些改变。

博客系统

目前使用的这个博客系统是放在DigitalOcean VPS的Wordpress 3.2.1。在迁移到VPS之前,我的博客是一直托管在同事的一个托管主机上的,当初从blogbus迁移到他的托管WordPress主机时使用的就是WordPress 3.2.1版本,这两年一直未动,目前WordPress版本都4.3.1了。WordPress 3.2.1有很多bug,尤其是其安全漏洞,今年就被黑过几次,为此在后台将blog纳入git version管理,这样被黑后就可以很容易恢复。但将版本升级到WordPress新版我还是担心的,主要是担心升级失败,尤其是>数据库表变化较大,担心无法恢复。

不过由于历史“负重”太大(900多篇),我很难将WordPress顺利平滑的切换到一些新博客系统,比如golang开发的hugoJekyllOctopress等,只能继续坚守WordPress。

由于经常在文章里贴代码,也曾尝试过使用一些语法高亮的插件,但目前使用的富文本编辑器CKEditor似乎总是与语法高亮不兼容,试了N多都不好用,尤其是在html编辑器和富文本编辑器切换时高亮>部分代码内容被自动转码,于是放弃。这样在文章中只能暂时用Courier New字体来“高亮”代码部分。

Crayon Syntax Highlighter

在尝试之初思路主要还是想找到一款与CKEditor兼容的好用的语法高亮插件,在网上找到一个插件组合:CKEditor + SyntaxHighlighter CKEditor Button + Auto-SyntaxHighlighter。安装后简单>测试了一下发现的确比之前找的几款插件强。输入代码时只需要点击CKEditor工具栏上的一个Code Button,SyntaxHighlighter CKEditor Button会打开一个源码输入对话框,选择源码的语言种类贴入源码即可,还可以在”高级”tab中设置一些选项,是否带行号等。这个组合最大的好处就是无需切换到html编辑器手工输入html tag。

不过测试一段时间后还是发现了这个插件组合的问题,那就是不支持Go语法。Auto-SyntaxHighlighter内部使用的是syntaxhighligter的js,后者已经停止更新,并且即便是最新版本也不支持golang。我只能fork一个Auto-SyntaxHighlighter的repo,并“照猫画虎”的Auto-SyntaxHighlighter增加Go语法文件:shBrushGo-min.js和shBrushGo.js,并修改SyntaxHighlighter CKEditor Button的js文件,增加Go选项。不过try后,发现高亮格式依旧不对,最初以为是我修改的不正确,后来发现即便是用其支持的C/C++代码,高亮格式依旧有问题,我怀疑是与我当前的theme不兼容所致。

在知乎上看到人们都推荐Crayon Syntax Highlighter这个语法高亮插件,于是想最后再尝试一下。安装后发现Crayon Syntax Highlighter的确强大,我将字体设置为monaco, 字号14,主题:monokai,其渲染出来的高亮代码和我在本地mac上的几乎一模一样。不过小问题还是有的,比如: 行号无法去掉,浮动工具栏不好用等。

Crayon插件的最大的问题还是使用不便:需要切换到html源码editor中手工加入:
<pre lang:"go"> </pre>

如果再切换到富文本编辑器后,再切回来,

<pre> </pre>

之间的文本就会被转码,这极大增加了使用门槛。在没有理想办法之前,只能将就着用吧。

以上已经让我折腾我几个小时了,凌晨一点,睡。

Markdown on Save Improved

早上醒来,想到了Markdown,也许是最后稻草了。以前一直以为WordPress版本较低,很多Markdown plugin都不支持。但今天先不管那些了,装上试试。我找到了Markdown on Save Improved,这款插件最大的好处就是可以在每篇文章级别上加markdown开启选项。目前该插件已>经停更,并且其作者基于该插件开发了”Jetpack’s Markdown module”,Jetpack太大,对WordPress版本要求也太高,于是我就选择了”Markdown on Save Improved”,满足我使用就可以了。安装插件后,有一个“Markdown on Save Improved Convert to Jetpack”提示,似乎点击一个按钮,就可以将该插件转换为”Jetpack’s Markdown module”,不过我>也不能肯定,因为从表面上看不出来,没有什么变化。

“Markdown on Save Improved”给我的最大惊喜是它居然兼容Crayon Syntax Highlighter,我将Crayon的默认语言设置为go,这样markdown标记的代码块后者渲染后展现出很理想的高亮效果。

package main

import "fmt"

func main() {
    fmt.Println("Hello, MarkDown and SyntaxHighlighter")
}

至于Markdown的预览,可以在stackedit.io上来做。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats