上次搭的博客写了两篇 Hexo 的配置后就凉了,所以这次刚刚搭好的时候就没想做个记录,怕和上次一样,把写博客的热情全花在了搭建博客上。

系统平台是 Ubuntu 17.04,其他平台的安装过程可能会有一些不同,不过后面的配置还是一样的。这里只有安装配置过程,具体使用,还请移步官方文档。
建议先看完再进行操作!!!

安装

hexo 是一个基于 node 的静态博客生成工具,所以先安装 node :

1
sudo apt install nodejs

这样安装似乎没有像 windows 下那样顺带把 npm 也给安装了,所以还需要安装一下 npm :

1
sudo apt install npm

再接着安装 Hexo:

1
sudo npm install hexo -g

很多朋友会遇到 Permission denied 的错误,所以我们需要使用 sudo 安装

1
2
3
4
# 在有读写权限的目录下执行,Blog 可以换成你喜欢的名字
mkdir Blog && cd Blog
# 初始化 Blog
hexo init

不出问题,写作环境就安装好了,再测试下:

1
2
3
4
# 生成静态资源
hexo g
# 在本地启动 node 静态资源服务器
hexo s

打开命令行里面输出的 http://27.0.0.1:4000,就能看到一篇 hello world

这里把安装命令整理一下:

1
2
3
4
5
6
sudo apt install nodejs npm
sudo npm install hexo -g
mkdir Blog && cd Blog
hexo init
# 下面的命令是为了安装某些正常安装但安装失败的依赖
npm install -f

目录结构

完成最基本的安装后, Blog 的目录结构大概是这样的

1
2
3
4
5
6
7
8
9
10
11
12
├── node_modules
├── scaffolds
│ ├── draft.md
│ ├── page.md
│ └── post.md
├── source
│ └── _posts
│ └── hello-world.md
├── themes
│ └── landscape
├── package.json
└── _config.yml

每个都简单说明一下:

  • node_modules

    差不多是一个本地运行环境,一般情况下是不需要动它的

  • sacffolds

    里面都是模板文件,可以打开看看,后面会进行一些修改

  • source

    这里放的是我们的源文件,文章和图片等

  • themes

    这里放的是一些主题,不同的文件夹就是不同的主题,目录名就是主题名

  • package.json

    Blog 工程的配置文件,一般情况下也不会动

  • _config.yml

    站点配置文件,定制化需要对它进行一些修改,我们下文也叫它 站点配置文件

站点基础配置

首先打开 站点配置文件,将 #Site 信息根据你的情况配置:

1
2
3
4
5
6
7
# Site
title: "Backyard"
subtitle: "敲敲代码,扯扯蛋"
description: "dashMrl's 个人小站————笔记+随笔"
author: dashMrl
language: zh-Hans
timezone:

然后修改 # Deployment 部分:

1
2
3
4
5
6
7
# Deployment
## Docs: https://hexo.io/docs/deployment.html
deploy:
type: git
branch: master
repo:
github: git@github.com:dashMrl/dashMrl.github.io.git

这里默认你知道怎么启用 GithubPages 服务,避免每次部署输入密码,我们使用 ssh密钥的方式部署

完成这些基本配置,就可以比较舒服的开始写博客了,如果你还需要更多定制化,接着往下看。

主题配置

到现在我们还是使用的默认主题 —— landscape,以我的审美来看,还是挺挫的。这里我们选择 Next 主题,这也是 GItHub 上 star 最多的一个主题。

如果觉得 Next 主题样式还行,也能满足你的大部分需求,就用它吧,其他的主题可能真的会有很多小问题,亲测

每个主题文件下都有一个 _config.yml 文件,这里我们就叫它 主题配置文件

首先去 Github 下载 Next 主题的 release 版本,解压到 thems 目录下,改名 next ,然后修改 站点配置文件

1
2
# Extensions
theme: next

再次执行 hexo g && hexo s 就可以看到生效的主题。

关于一些基本的配置,Next 的使用文档上都有,这里就只调我觉得重要的讲

阅读更多按钮

默认情况下首页会将整篇文章显示出来,非常丑陋并且影响阅读,所以有时候只想显示一小段描述。

主题配置文件 中找到 auto_excerpt

1
2
3
4
5
# Automatically Excerpt. Not recommend.
# Please use <!-- more --> in the post to control excerpt accurately.
auto_excerpt:
enable: true
length: 80

上面这种方式是截取 前 80 字符作为描述,如果想要精确控制的话,关闭 auto_excerpt使用 <--! more --> 来截断。我比较懒,就直接默认截取前80了。

back 2 top 按钮设置

主题配置文件 找到 sidebar 设置项,将相应子设置改成:

1
2
3
4
5
# Scroll percent label in b2t button.
scrollpercent: true

# Enable sidebar on narrow view (only for Muse | Mist).
onmobile: true

这样就能够在 backtotop 按钮上显示当前阅读的百分比了。

字数统计

主题配置文件 找到 Post wordcount display settings ,修改成下面样:

1
2
3
4
5
6
7
8
# Post wordcount display settings
# Dependencies: https://github.com/willin/hexo-wordcount
post_wordcount:
item_text: true
wordcount: true
min2read: true
totalcount: true
separated_meta: true

配置完后我们还需要安装 hexo-wordcount 插件:

1
npm install hexo-wordcount --save-dev

这样就能显示每篇文章字数和大概阅读时长,同时在页面底部显示整个站点的字数,,感觉挺有用的。

本地搜索

主题配置文件 中找到 #Local Search ,修改成这样:

1
2
3
4
5
6
7
8
9
# Local search
# Dependencies: https://github.com/flashlab/hexo-generator-search
local_search:
enable: true
# if auto, trigger search by changing input
# if manual, trigger search by pressing enter key or search button
trigger: auto
# show top n results per article, show all results by setting to -1
top_n_per_article: 1

然后在 站点配置文件 里你开心的位置加上/修改:

1
2
3
4
5
6
# Local Search
search:
path: search.xml
field: post
format: html
limit: 10000

最后安装插件:

1
npm install hexo-generator-search --save-dev

还有更多的细节配置,就不一个个讲了,自己看 主题配置文件 ,里面都有介绍,按照自己的需求配置就行了。

高级定制

有时候还需要对博客进行一些优化配置,比如资源压缩等,需要我们添加一些插件甚至修改框架文件。

文章链接优化

默认情况下,文章链接是 year/month/day/title 的形式,这样的链接层级对搜索引擎很不友好,当标题里包含中文的时候链接还会因为编码的问题变得丑陋异常。这里我们使用 hexo-abbrlink 插件对此进行优化。

站点配置文件 里找到 #URL 配置部分,然后修改成下面这样:

1
2
3
4
5
6
7
8
9
# URL
## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'
url: https://xinsbackyard.tech
root: /
permalink: posts/:abbrlink.html
permalink_defaults:
abbrlink:
alg: crc32
rep: hex

这样每篇文章就会有一个类似 f4a6041.html 的链接了,而且还提升了逼格。

配置完了记得安装插件(虽然应该先安装再配置来着的)

RSS 订阅

提供 RSS 订阅功能,让关注我们博客的朋友及时收到新文章的“推送”,虽然我自己没有用过 RSS ,但是感觉还是很牛逼的样子,既然这么牛逼,肯定要加上。

站点配置文件 中你开心的位置上加上:

1
2
3
4
5
6
7
8
9
# RSS
feed:
type: atom
path: atom.xml
limit: 20
hub:
content:
content_limit: 140
content_limit_delim: ' '

然后安装 hexo-generator-feed 插件。

添加站点运行时长

在网页底部显示 本站已运行 0 年 12 天 1 小时 33 分钟 4 秒 这样的字样,虽然并没有什么实质上的作用,但是以后看着自己的博客运行了这么久,发布了多少篇文章还是挺不错的。

这里以 Next 主题为例,其它的主题应该类似的

在 next 文件夹找到 layout/_partials/footer.swig 文件,然后找到这一段:

1
2
3
{% if theme.footer.custom_text %}
...
{% endif %}

在它前面加上 <div id="showDays">本站已运行 0 年 0 天 0 小时 0 分钟 0 秒</div> ,然后在它后面加上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<script>
var seconds = 1000;
var minutes = seconds * 60;
var hours = minutes * 60;
var days = hours * 24;
var years = days * 365;
var birthDay = Date.UTC(2017,12,19,14,00,00); // 这里设置建站时间
setInterval(function() {
var today = new Date();
var todayYear = today.getFullYear();
var todayMonth = today.getMonth()+1;
var todayDate = today.getDate();
var todayHour = today.getHours();
var todayMinute = today.getMinutes();
var todaySecond = today.getSeconds();
var now = Date.UTC(todayYear,todayMonth,todayDate,todayHour,todayMinute,todaySecond);
var diff = now - birthDay;
var diffYears = Math.floor(diff/years);
var diffDays = Math.floor((diff/days)-diffYears*365);
var diffHours = Math.floor((diff-(diffYears*365+diffDays)*days)/hours);
var diffMinutes = Math.floor((diff-(diffYears*365+diffDays)*days-diffHours*hours)/minutes);
var diffSeconds = Math.floor((diff-(diffYears*365+diffDays)*days-diffHours*hours-diffMinutes*minutes)/seconds);
document.getElementById('showDays').innerHTML="本站已运行 "+diffYears+" 年 "+diffDays+" 天 "+diffHours+" 小时 "+diffMinutes+" 分钟 "+diffSeconds+" 秒";
}, 1000);
</script>

这时候就可以在网页底部显示运行时间了。不过问题也来了,当我们在手机浏览器中加载网页的时候,底部因为太高而挡住了帖子中阅读更多按钮,所以为了避免这种情况,我们把 Powered by Hexo 等推广字样去掉(在这里对 Hexo 和 Next 说声抱歉)。

站点配置文件 里找到 footer: 配置,然后修改:

1
2
3
4
5
6
footer:
#...
powered: false
theme:
#...
enable: false

这样就算完成了。

如果学过 web 开发的话,可以把它们改得“面目全非”

修改 tag 图标

每篇文章底部都会显示几个 #tagname ,这个 # 号觉着不怎么好看,换成图标。

在 next 文件夹中找到 layout/_macro/post.swig ,找到 :

1
2
3
4
5
6
7
{% if post.tags and post.tags.length and not is_index %}
<div class="post-tags">
{% for tag in post.tags %}
<a href="{{ url_for(tag.path) }}" rel="tag"> #{{ tag.name }}</a>
{% endfor %}
</div>
{% endif %}

{{ tag.name }} 前面的 # 改成 <i class="fa fa-tag"></i> 。这样就 OK 了。

静态资源压缩

Hexo 生成的静态资源中有很多的空行空格,然后我们的图片也有比较大的优化空间,为了减小它们的体积,提高加载速速,需要对其进行一定程度的压缩。

这里我们使用 Gulp 来压缩资源,首先安装必要的依赖:

1
npm install gulp gulp-clean-css gulp-html-clean gulp-htmlmin gulp-imagemin gulp-uglify --save-dev

然后在博客根目录下添加 gulpfile.js 文件,并写入如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
var gulp = require('gulp');
var minifycss = require('gulp-clean-css');
var uglify = require('gulp-uglify');
var htmlmin = require('gulp-htmlmin');
var htmlclean = require('gulp-htmlclean');
var imagemin = require('gulp-imagemin');

// 压缩html
gulp.task('minify-html', ()=> {
return gulp.src('public/**/*.html')
.pipe(htmlclean())
.pipe(htmlmin({
removeComments: true,
collapseWhitespace: true,//压缩HTML
removeEmptyAttributes: true,//删除所有空格作属性值 <input id="" /> ==> <input />
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
}))
.pipe(gulp.dest('public'))
});
// 压缩css
gulp.task('minify-css', ()=> {
return gulp.src(['public/css/**/*.css', '!public/css/**/*min.css'])
.pipe(minifycss({ compatibility: 'ie8' }))
.pipe(gulp.dest('public/css'));
});
// 压缩js
gulp.task('minify-js', ()=> {
return gulp.src(['public/js/**/*.js', '!public/js/**/*min.js'])
.pipe(uglify())
.pipe(gulp.dest('public/js'));
});
// 压缩图片
gulp.task('minify-images', ()=> {
return gulp.src('public/images/**/*.*')
.pipe(imagemin(
[imagemin.gifsicle({ 'optimizationLevel': 3 }),
imagemin.jpegtran({ 'progressive': true }),
// 在我电脑上下面这一行会报错
// imagemin.optipng({ 'optimizationLevel': 5 }),
imagemin.svgo()],
{ 'verbose': true }))
.pipe(gulp.dest('public/images'))
});
// 默认任务
gulp.task('default', [
'minify-html', 'minify-css', 'minify-js', 'minify-images'
]);

然后在每次部署博客之前都执行:

1
gulp

如果站点的文本文件比重大的话,压缩效果还是很可观的。

SEO 优化

其实 SEO 也可以放在上一节中,但是 SEO 算是比较不同的配置,所以就拿出来单独讲。

生成 sitemap

我们需要把站点内容主动推给搜索引擎,推送载体就是 sitemap。打开 站点配置文件 ,在你开心的位置添加上:

1
2
3
4
5
# Site Map
sitemap:
path: sitemap.xml
baidusitemap:
path: baidusitemap.xml

然后安装 hexo-generator-sitemaphexo-generator-baidu-sitemap 两个插件。

认证网站所有权

这里需要分 Google 和 百度 分别认证,具体怎么认证,有很多优秀的博客有讲,这里就不赘述了

主动/自动推送

这里主要是针对百度的,因为 Github 把百度的爬虫给屏蔽了(虽然不知道为什么,但觉得百度好委屈hhh)。在百度站长认证完网站所有权之后就可以推送链接了,有被动爬取(被屏蔽)、自动推送和主动推送三种方式。

要开启自动推送非常简单,Next 帮我们把推送脚本内置了,只需要在 主题配置文件 里开启 baidu_push: true 就可以了。

至于主动推送,就是我们按照一定格式手工推送链接。emmm,手工?不存在的,这么无聊的事情肯定要自动化,然后就是考虑推送时机,更新博客的时候最合适,所以我们写一个博客的 部署脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/bin/bash
statusCheck(){
if [ $? != 0 ]
then
echo -n $1' failed!!\n'
exit $?
else
echo -n $1' completed!!\n'
fi
}
echo 'start cleaning...'
node_modules/hexo/bin/hexo clean
statusCheck 'cleaning public resource'

echo 'start generating...'
node_modules/hexo/bin/hexo g
statusCheck 'generating public resource'

echo 'start compressing by gulp...'
node_modules/gulp/bin/gulp.js
statusCheck 'compressing public resource'

echo 'start deploying...'
node_modules/hexo/bin/hexo d
statusCheck 'deploying to repository'

echo 'start upload sitemap to baidu'
cat public/sitemap.xml | grep loc| grep -o 'https://xinsbackyard.tech/posts/.*\.html' > public/urls.txt
curl -H 'Content-Type:text/plain' --data-binary @public/urls.txt "http://data.zz.baidu.com/urls?site=https://xinsbackyard.tech&token=tZapjdbbZwBxt7WV"
#rm public/urls.txt
statusCheck 'push links to baidu'

echo 'completed...'

PWA 改造

PWA(渐进式 WebApp)在国内还一直不愠不火,但是 PWA 在提高用户体验方面确实有很大的作用,国外有很多案例(没亲自考证)。更重要的一点是,如果你使用原生系统,并且使用 Chrome 浏览 PWA 改造过的站点,Chrome 会根据用户的浏览情况来弹出 添加该站点到主屏幕 的请求窗口,当点击确认后, 应用抽屉 里就会出现一个你站点的 “App”,你没看错,是和我们从应用商店安装的应用待在一个地方,而且还能在系统设置里看到它。

manifest.json

就像一个 Android App 一样,我们需要提供一个清单文件来描述我们的站点,它大概长这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{
"name": "Backyard",
"short_name": "Backyard",
"description": "dashMrl's 后花园——笔记+随笔",
"dir": "auto",
// 这里设置成 standalone 很重要,不然不会显示为一个单独的应用
"display": "standalone",
// 下面的两个颜色可以设置一样,会配合图标生成一个启动页
"theme_color": "#272727",
"background_color": "#272727",
"start_url": "/?pwa=true",
"scope": "/",
// 下面是 PWA 安装到手机上后显示的图标,最高需要提供到 512x512(我找遍了都没找到我头像这种分辨率的图,QAQ)
"icons": [
{
"src": "images/icons/touch48.png",
"sizes": "48x48",
"type": "image/png"
},
{
"src": "images/icons/touch72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "images/icons/touch96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "images/icons/touch144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "images/icons/touch168.png",
"sizes": "168x168",
"type": "image/png"
},
{
"src": "images/icons/touch192.png",
"sizes": "192x192",
"type": "image/png"
}
]
}

然后把这个文件丢到 source 文件夹下面,再修改 .../themes/next/layout/_partials/head.swig 文件使得每个页面都声明 manifest :

1
2
3
...
<link rel="manifest" href="/manifest.json">
...

还有一些辅助我们生成这个文件的网站,大家可以自行搜索,如果想要深入了解这个文件,可以前往 MDN 上学习。

Service Worker

这算是 PWA 精髓所在了,它的作用可以不恰当地理解为缓存。当我们第一次浏览某个网页的时候,浏览器会尝试注册这个 ServiceWorker,此时处于 installing 状态,注册成功后它就会运行在一个单独的进程,并处于 active 状态,然后当我们请求我们站内资源的时候,请求就会先经过 sw ,如果它恰好有缓存的话,直接返回,否则进行网络请求。当我们下一次访问这个站点的时候,如果 sw 的缓存没有过期,我们就可以接着使用缓存(和浏览器本身缓存很像)。

说了这么多,那到底怎么才能使用 sw 呢?也非常简单,首选打开 站点配置文件 ,在合适的位置加入 :

1
2
3
4
5
6
7
# offline config passed to sw-precache
service-worker:
maximumFileSizeToCacheInBytes: 5242880
staticFileGlobs:
- public/**/*.{js,html,css,png,jpg,gif,webp,svg,eot,ttf,woff,woff2}
stripPrefix: public
verbose: true

然后安装 hexo-offline 插件就可以了,这时候执行 hexo g 可以看到类似 “ INFO Total precache size is about 5.17 MB for 153 resources ” 的字样,然后在 public 目录下会出现一个 service-worker.js 文件,这就表示它能缓存我们整个站点的文件。

启用 HTTPS

PWA 要求站内所有资源都通过 HTTPS 传输,如果使用的 GithubPages 的话,默认开启 HTTPS ,不需要我们操心。但是如果配置了自定义域名,GitHub 提供的 HTTPS 就无法开启了,如果你也和我一样想省时省钱的话,就是用 cloudflare 来提供 HTTPS 服务吧。具体怎么玩,大家自己亲自去实践吧hhh。

到现在应该是写得差不多了,写教程类的文章总是最累的(所以我偷工减料),即怕说得不够清楚,又怕说得太多不利于读者思考,更怕误导读者,所以还是向所有为人师者致敬。