Hexo的美化、优化以及Lighthouse极致追分

2021-04-04 10:28≈ 544字≈ 3分钟

之前写过一篇 利用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<div class="footer">
 2  <div class="social">
 3    <ul>
 4      <% for(let item of theme.footer.social){ %>
 5        <% if (item.name == "email") { %>
 6          <li>
 7            <a title="<%- item.name %>" href="mailto:<%- item.path %>">
 8              <i class="iconfont icon-<%- item.icon %>"></i>
 9            </a>
10          </li>
11        <% } else { %>
12          <li>
13            <a title="<%- item.name %>" href="<%- item.path %>">
14              <i class="iconfont icon-<%- item.icon %>"></i>
15            </a>
16          </li>
17        <% } %>
18      <% } %>
19    </ul>
20  </div>
21  <% for(let item of theme.footer.more){ %>
22    <div class="footer-more">
23      <% if (item.path) { %>
24        <a href="<%- item.path %>"><%- item.name %></a>
25      <% } else { %>
26        <%- item.name %>
27      <% } %>  
28    </div>
29  <% } %>
30</div>

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

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

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

 1<div class="container index">
 2  <div class="post-list">
 3    <!-- 遍历渲染文章 -->
 4    <% 
 5    var prev = -10086;// prev year
 6    var curr;// curr year, ever step be updated 
 7
 8    page.posts.forEach(function(item) { 
 9      var mark = true;
10      item.categories.forEach(function(item1){
11        if(item1.name == "novel" || item1.name == "gossip"){
12          mark = false;
13        }          
14      });
15      if(mark){
16        curr = item.date.year()
17        if (curr !== prev) {
18          prev = curr;
19
20    %>
21    <div class="content-title">
22      <h2>
23        <span><%- curr %></span>
24      </h2>
25    </div>
26    <%
27      }
28    %>
29      <div class="post-item" title="<%- item.title %>">
30        <div class="time-m-d"><%- item.date.format("MM-DD") %></div>
31        <div class="title">
32          <a href="<%- url_for(item.path) %>">
33            <% if(item.title !== "") { %>
34              <% if (item.top) { %>
35                <span><span title="<%= __('pinned') %>" class="icon iconfont icon-pin-top post-top"></span><%- item.title %></span>
36              <% } else { %>
37                <span><%- item.title %></span>
38              <% } %>
39            <% } else { %>
40              <span>untitled</span>
41            <% } %>
42          </a>
43        </div>
44      </div>
45    <% }}) %>
46  </div>
47  <nav class="post-navigation">
48    <% if(page.prev !== 0){ %>
49      <a href="<%- url_for(page.prev_link)%>"><i class="iconfont icon-angleleft"></i></a>
50    <% } %>
51    <span class="page-num"><%- page.current %> / <%- page.total -%></span>
52    <% if(page.next !== 0){ %>
53      <a href="<%- url_for(page.next_link)%>"><i class="iconfont icon-angleright"></i></a>
54    <% } %>
55  </nav>
56</div>

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

image-20210404105509804

修改hexo-generator-index分页

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

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

 1'use strict';
 2
 3const pagination = require('hexo-pagination');
 4const { sort } = require('timsort');
 5
 6module.exports = function(locals) {
 7  const config = this.config;
 8  const posts = locals.posts.sort(config.index_generator.order_by);
 9  const temp_posts = [];
10
11  sort(posts.data, (a, b) => (b.sticky || 0) - (a.sticky || 0));
12
13  const paginationDir = config.pagination_dir || 'page';
14  const path = config.index_generator.path || '';
15
16  if(config.index_generator.exclude){    
17    posts.forEach(element => {
18      var mark=true; 
19      element.categories.forEach(function(categories){ 
20        config.index_generator.exclude_list.forEach(function(category){
21          if(categories.name == category){
22            mark=false; 
23          }
24        });
25      }); 
26      if(mark){
27        temp_posts.push(element);
28      }    
29    });
30  }
31
32  return pagination(path, config.index_generator.exclude ? temp_posts : posts, {
33    perPage: config.index_generator.per_page,
34    layout: ['index', 'archive'],
35    format: paginationDir + '/%d/',
36    data: {
37      __index: true
38    }
39  });
40};

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

1index_generator:
2  path: ''
3  per_page: 10
4  order_by: -date
5  exclude: true
6  exclude_list:
7    - novel
8    - 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分,当然还有进步的空间,只是日后有机会再折腾吧