Hexo的美化、优化以及Lighthouse极致追分
2021-04-04 10:28 ≈ 2.4k字 ≈ 10分钟

之前写过一篇 利用Hexo、GitHub Page、Typora写文章详细分享了我安装Hexo的过程,今天来聊一聊我这几天做文章迁移,选择Hexo主题,以及做主题修改和Hexo分页修改的过程,最后还会简单说一下如何在Lighthouse达到100分的跑分

Hexo美化

首先,Hexo安装完毕之后目前默认的是landscape这个主题,也很简洁,专注于写文章的人直接用完全没问题。不过我之前在使用Halo的时候用的就是Next主题,因此这次迁移第一个想法就是仍然使用next

主题安装

有意思的是我没有直接搜索next,而是在Hexo的官方主题库里面想要找到next,我想这是一种缘分,让我发现了Oranges这个主题,可以看一下Demo,这个主题比next还要简洁

image-20210404103130252

去掉了所有可变按钮和分栏,这样就带来一个好处,移动端的时候选择其他标签按钮不需要再点一个下拉菜单了,就这一点点的简化让我选择了这个主题

安装过程很简单,只有两个步骤:

  1. $ git clone https://github.com/zchengsite/hexo-theme-oranges.git themes/oranges

  2. 修改hexo根目录的_config.yml 文件,把theme改成oranges即可

主题配置

在正式使用主题之前,还可以基于主题进行一些个性化配置,看得出来作者对于一些功能的开启有着很严格的标准,基本上在Readme文件当中罗列的功能都是基本需要的,可以在这里查看,由于作者的文档非常详细了,就不额外罗列了,我只简单说一下我开启的功能:

分类、标签、文章目录、RSS、评论、Google Analytics、上下页、全文搜索

图片懒加载没有开启,主要是觉得本来图片已经用了图床+CDN了,再多一个懒加载多此一举,而且观感不太好,要先看一个未加载的图片

主题修改

下面来聊一聊我改动了哪些地方,比较碎,咱们一点一点说

footer当中添加邮箱识别

image-20210404104415928

在这里的所有图标都对应一个网址,因此作者在处理的时候就直接将配置文件的地址写入<a>标签的href里面了,但是作为邮箱,是需要在href里面加上一个mailto:的,可是由于里面有一个:的原因,直接写在配置文件里面会报错,因此我修改了代码如下:

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
<div class="footer">
<div class="social">
<ul>
<% for(let item of theme.footer.social){ %>
<% if (item.name == "email") { %>
<li>
<a title="<%- item.name %>" href="mailto:<%- item.path %>">
<i class="iconfont icon-<%- item.icon %>"></i>
</a>
</li>
<% } else { %>
<li>
<a title="<%- item.name %>" href="<%- item.path %>">
<i class="iconfont icon-<%- item.icon %>"></i>
</a>
</li>
<% } %>
<% } %>
</ul>
</div>
<% for(let item of theme.footer.more){ %>
<div class="footer-more">
<% if (item.path) { %>
<a href="<%- item.path %>"><%- item.name %></a>
<% } else { %>
<%- item.name %>
<% } %>
</div>
<% } %>
</div>

当配置文件里面的社交名为email的时候,在代码里面添加mailto:

首页文章列表去掉某个分类

这个需求我不知道其他人有没有,因为我的博客里面除了技术的文章,还会放一些小说,以及每日一段话类似之前的说说,全都堆在首页列表里面显得非常混乱,因此我修改了代码,将某个分类从列表中去掉(去掉几个都无所谓),代码改动不多,但是结构比较复杂,所以我把index.ejs全部贴出来,你们想要改的话直接复制就好,然后再手动改第11行即可

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
50
51
52
53
54
55
56
<div class="container index">
<div class="post-list">
<!-- 遍历渲染文章 -->
<%
var prev = -10086;// prev year
var curr;// curr year, ever step be updated

page.posts.forEach(function(item) {
var mark = true;
item.categories.forEach(function(item1){
if(item1.name == "novel" || item1.name == "gossip"){
mark = false;
}
});
if(mark){
curr = item.date.year()
if (curr !== prev) {
prev = curr;

%>
<div class="content-title">
<h2>
<span><%- curr %></span>
</h2>
</div>
<%
}
%>
<div class="post-item" title="<%- item.title %>">
<div class="time-m-d"><%- item.date.format("MM-DD") %></div>
<div class="title">
<a href="<%- url_for(item.path) %>">
<% if(item.title !== "") { %>
<% if (item.top) { %>
<span><span title="<%= __('pinned') %>" class="icon iconfont icon-pin-top post-top"></span><%- item.title %></span>
<% } else { %>
<span><%- item.title %></span>
<% } %>
<% } else { %>
<span>untitled</span>
<% } %>
</a>
</div>
</div>
<% }}) %>
</div>
<nav class="post-navigation">
<% if(page.prev !== 0){ %>
<a href="<%- url_for(page.prev_link)%>"><i class="iconfont icon-angleleft"></i></a>
<% } %>
<span class="page-num"><%- page.current %> / <%- page.total -%></span>
<% if(page.next !== 0){ %>
<a href="<%- url_for(page.next_link)%>"><i class="iconfont icon-angleright"></i></a>
<% } %>
</nav>
</div>

和主题原本不一样的是,我在列表当中将年度提取出来单独展示,这样观感好一些,当然也是从归档页抄来的

image-20210404105509804

修改hexo-generator-index分页

需要注意的是,除非你不用分页(似乎不太可能),如果使用系统分页,那么系统自己再分页的时候,是不会把你想要去除的文章去掉的,这会导致一个问题,就是比如你按10个文章一分,但是主页只显示7个文章,那么分页后这个页面就是7个文章,如果正好某一页全都是你要去除的文章,那么这个页面上就会什么都没有,这和我们的初衷相违背,因此我们想要达到更好的观感,也需要修改Hexo的分页程序

修改的位置就在你博客的根目录node_modules文件夹里面,找到hexo-generator-index这个文件夹当中的generator.js这个文件,用vscode或者记事本打开也可以,在文章数组生成后,调用分页函数之前,添加一段代码,我的方法是新建一个数组,然后将老数组加一个判断,将未排除的文章推入新的数组即可,代码如下,改动从第16行开始

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
'use strict';

const pagination = require('hexo-pagination');
const { sort } = require('timsort');

module.exports = function(locals) {
const config = this.config;
const posts = locals.posts.sort(config.index_generator.order_by);
const temp_posts = [];

sort(posts.data, (a, b) => (b.sticky || 0) - (a.sticky || 0));

const paginationDir = config.pagination_dir || 'page';
const path = config.index_generator.path || '';

if(config.index_generator.exclude){
posts.forEach(element => {
var mark=true;
element.categories.forEach(function(categories){
config.index_generator.exclude_list.forEach(function(category){
if(categories.name == category){
mark=false;
}
});
});
if(mark){
temp_posts.push(element);
}
});
}

return pagination(path, config.index_generator.exclude ? temp_posts : posts, {
perPage: config.index_generator.per_page,
layout: ['index', 'archive'],
format: paginationDir + '/%d/',
data: {
__index: true
}
});
};

然后在系统的配置文件_config.yml里面添加要排除的分类名称

1
2
3
4
5
6
7
8
index_generator:
path: ''
per_page: 10
order_by: -date
exclude: true
exclude_list:
- novel
- gossip

到这里,基本上有关视觉的改动就差不多了

快!一定要快

接下来,我修改的部分主要是为了打开速度,既然选择了这么简洁的主题,那么Lighthouse跑分跑不到100分多丢人? 下面是我的主页的跑分,包括桌面端和移动端

要怎么做呢,其实google给出了很多建议,这里我只说一下我针对主题的一些做法

将所有静态文件保存在CDN

方法也很简单,将主题目录上传到github的一个公共仓库,然后发布一个release版本,这样你这个版本里面的静态文件都会缓存到jsdelivr里面,调用的方法也很简单

https://cdn.jsdelivr.net/gh/你的用户名/你的仓库名@Release版本号/source/iconfont/iconfont-min.css

将js文件异步加载

有了CDN地址之后,将主题里面所有的资源都改用CDN,主要是在/layout/_partial/header.ejs里面,还有几个零散的地方,自己看下source/*里面的文件,有哪些要修改的改下就可以了,Lighthouse跑一下也会有对应的提示,记得将所有的js文件的加载都添加async关键字,jquery.min 在这里是为了全文搜索使用的,加载的时候不涉及,jquery.fancybox.min-3.5.2 在这里是为了文章点击图片放大使用,也不涉及到一开始的页面渲染,所以放心加没关系,不要让这些js文件阻碍页面渲染

将所有js和css文件都进行压缩

这个是标准动作啦,直接搜索css压缩,会有很多在线压缩的网站,将文件复制进去点一下压缩,再创建一个XX-min.js的文件保存就可以了

至此经过一顿折腾,我的页面桌面模拟100分,移动端模拟99分,当然还有进步的空间,只是日后有机会再折腾吧