什么是hexo?

Hexo 是一个快速、简洁且高效的博客框架。 Hexo 使用 Markdown(或其他标记语言)解析文章,在几秒内,即可利用靓丽的主题生成静态网页(html)。

其他博客框架:vuepress , gatsby;前者适合vue开发者,后者适合react开发者。

安装hexo

需要提前准备的工具:vscode, git, node.js;去对应的官网下载即可。

在任意位置新建一个文件夹,右键选择用vscode打开;或者直接打开vscode新建一个文件夹,取一个合适的名字,比如blog;右键文件夹,在当前文件下打开终端,执行以下命令:

1
2
3
4
5
npm install -g hexo-cli //全局安装hexo
hexo init blog //初始化一个博客blog
cd blog //进入到博客文件
npm install //安装所需依赖
hexo server //在本地部署博客

好了,再访问http://localhost:4000就能看到运行在本地的博客了

hexo常用指令

1
2
3
4
hexo clean //用于清理由 Hexo 生成的缓存文件和静态文件(public文件)
hexo generate //可以简写为hexo g,作用是生成静态文件
hexo server //可以简写为hexo s,部署自己的博客到本地,会打包文件但是不会输出实际文件
hexo deploy //部署自己的博客到服务器

项目结构分析

  • node_modules:存放安装到本项目的npm包
  • scaffold:存放md文档模板
    • page.md:页面的模板
    • post.md:博客的模板
  • source:存放博客和页面的文件夹
    • _post:存放博客的文件夹,里面都是md文件,最终会被编译成html文件
    • categories:存放分类页面的文件夹,通常只有一个文件
    • tags:存放标签页面的文件夹,通常只要一个文件
  • theme:存放下载的主题的文件夹
  • _config.yml:博客的配置文件
  • _config.主题名.yml:主题的配置文件,自定义主题配置的地方

更换主题:butterfly

hexo自带的主题也许不是那么好看,没关系,hexo提供了丰富的主题给我们选择,我们可以去官网上查找,或者去GitHub上查找(推荐),下面我们以GitHub为例。

在国内直接访问github很不稳定,需要借助加速器,这里推荐steam++

没有账号的用自己的邮箱注册一个即可,登录后在home主界面搜索hexo themes,查找自己喜欢的主题,这里我们选择butterfly主题。

  • 下载
1
git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly
  • 在你的博客文件夹的themes文件夹中,就能看到butterfly文件夹,删除.git文件夹。
  • 在博客根目录下新建_config.butterfly.yml文件,复制themes/butterfly文件夹下的_config.yml文件内容,粘贴到该文件,后续自定义博客几乎都在这个配置文件中进行。

新建博客文章

1
hexo new 文章名

执行这条命令之后你就能在source/_post文件夹下看到一个新的md文件,它就是你编写博客的地方,所以在这之前,我们需要学习一下md语法,其实也是非常简单的。

md文件结构分析

  • Front-matter:是 markdown 文件最上方以---分隔的区域,不是写博客的区域,而是配置博客的区域
    • Page-Front-Matter:用于 页面 配置
    • Post Front-matter:用于 文章页 配置

具体是配置什么的直接看文档Butterfly 文檔(二) 主題頁面 | Butterfly

  • 用md语法写博客的区域

修改博客下方的文章链接

在根目录下的_config.yml文件中修改,确保url是你博客部署的网址,替换掉默认的示例。

1
2
3
# URL
## Set your site url here. For example, if you use GitHub Page, set url as 'https://username.github.io/project'
url: https://www.sanye.blog

修改博客分享方式

1
2
3
4
5
6
7
8
9
share:
# Choose: sharejs / addtoany
# Leave it empty if you don't need share
use: sharejs #选择提供分享功能的服务商,不需要分享功能则置空

# Share.js
# https://github.com/overtrue/share.js
sharejs:
sites: wechat,weibo,qq #选择分享到哪些平台

新建分类

为了方便我们博客文章的查找,我们很自然的会想到给博客分类,执行如下命令:

1
hexo new page categories //本质是在创建一个页面page

你会找到source/categories/index.md这个文件

修改这个文件的Front-Matter部分:

1
2
3
title: 分类  
date: 2018-01-05 00:00:00
type: 'categories'

然后我们在每篇博客的Front-matter部分就可以通过categories属性给文章分类。示例:categories: 'book'

注意:如果我们未创建分类页面,点击分类标签是会报错的,提示找不到该页面。

之后我们点击’分类’,就可以成功跳转到分类页面,但是,我们可以观察到,分类页没有顶部图片,是纯蓝色,不够美观,其实我们只要在source/categories/index.mdFront-matter部分添加一个top_img属性,指定顶部图片的路径即可。

1
2
3
4
5
6
---
title: 文章分类
date: 2024-11-24 21:38:53
type: 'categories'
top_img: /images/cover/江南.png
---

新建标签

我们还可以给每篇文章添加多个标签,执行如下命令:

1
hexo new page tags //本质也是在创建一个页面page

你会找到source/tags/index.md这个文件

修改这个文件的Front-Matter部分:

1
2
title: tags
type: 'tags'

然后我们在每篇博客的Front-matter部分就可以通过tags属性给文章添加标签,一篇文章可以添加多个标签,示例:

1
2
3
4
//要注意缩进,否则可能报错
tags:
- 'html'
- 'css'

注意:如果我们未创建tags页面,点击tags标签是会报错的,提示找不到该页面。

给tags页面添加top_img的方法同上文

自定义主页

博客的主页就是博客的首页,如下:

自定义主页的详细内容见官方文档Butterfly 文檔(三) 主題配置 | Butterfly,下面我只介绍我遇到困难的部分。

自定义菜单

_config.butterfly.yml文件中设置:

1
2
3
4
menu:
Home: / || fas fa-home
Tags: /tags/ || fas fa-tags
Categories: /categories/ || fas fa-folder-open

当然这些都是我认为最基础的菜单设置,||前面的表示的是页面的路径,后面表示的是图标

在自定义这部分的时候我遇到了一个问题,就是无论如何配置,菜单上都会有music和video选项,原因是在themes/butterfly_config.yml文件中,music和video选项是默认选中的。Hexo 会自动合并主题中的 _config.yml_config.butterfly.yml 里的配置,如果存在同名配置,会使用_config.butterfly.yml的配置,其优先度较高。参考文档Butterfly 文檔(一) 快速開始 | Butterfly

添加搜索功能

如果能根据本地博客内容实现文章搜索,那实在是太方便了;hexo提供了多种搜索方式,其中本地搜索最容易实现。

前往博客根目录,打开cmd命令窗口执行:

1
npm install hexo-generator-search --save

然后在_config.butterfly.yml文件中配置即可

1
2
3
4
search:
# Choose: algolia_search / local_search / docsearch
# leave it empty if you don't need search
use: local_search

更多搜索方式参考文章:Hexo + Butterfly 键入搜索功能 - 简书以及butterfly官方文档

自定义首页图片

1
2
3
4
5
6
# 禁用顶部图片
disable_top_img: false
# The banner image of index page
index_img: #指定顶部图片
# The height of top_img, eg: 300px/300em/300rem
index_top_img_height: 16rem #指定顶部图片的高度

这三个配置项默认并不在一起,但是我为了方便配置把它们放到了一起。

引入图片

  • 通过网络图片的形式引入

    优点:减小打包体积

    缺点:博客部署在github使用网络图片可能存在跨域问题

  • 通过本地图片引入

    优点: 不存在跨域问题,直接使用本地图片即可。

    引入方式:在根目录下的source文件夹中新建一个images文件夹,然后本地图片都放里面(假设放入了一张图片xxx.jpg),然后博客文章就能通过../images/xxx.jpg的相对路径来访问了。

    而且为了让我们的博客图片无论在本地直接打开博客md文件的时候能正常显示,还是在部署到本地或者远程服务器的时候能正常显示,我们需要用img标签来展示我的图片,而不是使用![]()这种md语法。

B站banner

用过B站的小伙伴应该都注意到了B站首页banner图片的特色,我们也可以用它来装饰自己的博客!

参考文章:Bilibili Dynamic Banner | Akilarの糖果屋

上述文章只给了2中banners,而且迁移到博客步骤比较多,所以我自己折腾了一下,当然也参考了别人的文章,并且部署到了github上:shiyuhuiya/BilibiliBannerToHexo: 把B站banner添加到自己的hexo博客!

自定义社交图标

如上图就是社交图标,可以在_config.butterfly.yml文件的social属性中配置,点击即可跳转到相关网页。

1
2
3
4
social:
fa-brands fa-bilibili: https://space.bilibili.com/660655866?spm_id_from=333.1007.0.0 || Bilibli || '#74C0FC'
fab fa-github: https://github.com/syhy || Github || '#24292e'
fas fa-envelope: mailto:3519450570@qq.com || Email || '#4a7dbe'

书写格式 图标名:url || 描述性文字 || color

图标名可在这个网站上查找:fontawesome

统计网站访客数目

我们的博客是纯静态网页,没有涉及到与后端的数据交互,但是我们如果想要实现统计网站访客数目的功能,就必须借助后端,那该怎么实现呢?幸运的是,有人愿意免费给我们提供服务器来存储我们网站的访客数据。

不蒜子 - 极简网页计数器 是一个轻量级的网站访问统计工具,它通过简单的 JavaScript 代码嵌入到网页中来实现访问次数的统计。

大致原理

当用户访问包含 Busuanzi 脚本的页面时,该脚本会在用户的浏览器上执行,然后发送一个jsonp请求,请求头中的Referer字段会携带当前网站的url,busuanzi服务器会从Referer字段中提取出网站的域名等信息,并将该域名对应的网站访问次数加1,再返回一串js代码,这串代码中包含了网站被访问次数等信息,然后浏览器会执行这串代码,把返回的信息渲染到页面上。具体原理参考源码

如官网所示,我们只需在网页中引入一个js文件就行,对于butterfly主题的hexo博客,用上这个工具更是简单,我们只需要在主题配置文件中启用这个插件就行:

1
2
3
4
busuanzi:
site_uv: true
site_pv: true
page_pv: true
1
2
3
# 确保开启webinfo,不然也不会显示访客数据
card_webinfo:
enable: true

博客网站访客量虚高的原因。

  • 我们的博客部署在本地localhost:4000,大家都用这个域名测试博客,访客量当然特别高了,部署到自己的网站后就没问题了。

  • 我们的博客网站所在域名之前可能已经使用过busuanzi提供的服务了,但是无论我们是按照官网的指示直接引入js文件,还是在butterfly的主题配置文件中开启相关配置,请求获取的都是官方的js文件,也就是源码,我们可以通过直接在浏览器导航栏输入官方js文件的网址(在官网已给出),从而下载,修改源码来解决这个问题。我们把下载好的源码放在themes/butterfly/source/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
// 我们先分析这三个字段什么意思
// "site_uv": 独立访客数
// "page_pv": 当前页面的访问量
// "site_pv": 站点总访问量
bszs: ["site_pv", "page_pv", "site_uv"],
texts: function (a) {
this.bszs.map(function (b) {
var c = document.getElementById("busuanzi_value_" + b);
if (c) {
switch (b) {
case "site_pv":
c.innerHTML = a[b]-虚高的值;
break
case "page_pv":
//文章链接通常是唯一的,出现二手的概率很小,所以直接使用返回过来的值
c.innerHTML = a[b]
break;
case "site_uv":
c.innerHTML = a[b] - 虚高的值;
break;
}
}
});
},

然后在主题配置文件中修改busuanzi的默认cdn链接,指定为本地文件。

1
2
3
CDN:
option:
busuanzi: /js/busuanzi.js

当然,如果我们的博客因为部署的域名改变了,需要加上先前的访问次数,也可以使用这种方式来实现。

live2D

参考:shiyuhuiya/shizuku: 优化live2d模型shizuku的交互效果

永久链接

Hexo 文章链接默认的生成规则是::year/:month/:day/:title,是按照年、月、日、标题来生成的。

这样的话,生成的链接非常长,而且如果我们的 Markdown 使用中文标题,那就更惨了,URL 一转码,将是一场灾难。

更难受的是如果我们修改了文章的日期或者标题,那么将导致链接改变,别人或者你分享出去的文章就会 404,这非常的蛋疼啊,但是只要使用了hexo-abbrlink插件,便可解决以上出现的问题,不论你如何修改文章的日期、名称,只要不改变 footer-matter 中的 id 值,那么文章链接永远不会变。

  • 安装:

    1
    npm install hexo-abbrlink --save
  • 修改_config.yml配置文件

    1
    2
    ## permalink: :year/:month/:day/:title/
    permalink: posts/:abbrlink.html

如果想要了解更多,去网上搜索资料即可,资料是非常多的。

自定义页脚

butterfly主题配置文件的footer.custom_text属性是支持传入html结构的,而其他footer属性不支持,我们可以选择关掉其他footer属性,把要定义的解构全写footer.custom_text里,可以放入一些彩色图标,添加更多结构,提供更大的自由度。

可以前往iconfont-阿里巴巴矢量图标库寻找自己喜欢的图标,根据说明操作即可。

1
2
3
4
5
6
7
footer:
owner:
enable: false
since: 2024
custom_text: <div id="sanye"><svg class="icon" aria-hidden="true"><use href="#icon-banquan"></use></svg><span>2024 - 2025 By 三叶sanye</span><svg class="icon" aria-hidden="true"><use href="#icon-sanyecao"></use></svg></div><div id="runtime"></div>
# Copyright of theme and framework
copyright: false

加载动画

如果我们的博客部署在GitHub,或者我们的博客打开需要加载较多的网络资源,就会导致我们的博客打开很慢,这个时候通过加入加载动画就能优化读者的阅读体验。

butterfly主题提供了默认的加载动画,但是可能不够美观,这时候我们就可以根据自己的喜好自定义了。

自定义loading的大概步骤:

  • 修改loading.pug
  • 修改loading.styl

参考文章:多种加载动画

我在做自己的博客的时候,并没有完全跟着博客敲代码,而是先大致了解一下代码的逻辑,然后只选择了其中的一种加载动画—钢铁之心,所以省去了很多步骤,如果有像我一样不喜欢加载完成后展开的过渡效果的,可以对source/css/_layout/loading.styl文件做如下修改:

1
2
3
4
5
6
7
8
&.loaded
display none
.loading-left-bg
transition all 1.0s
transform translate(-100%, 0)
.loading-right-bg
transition all 1.0s
transform translate(100%, 0)

意思就是,页面加载完毕之后,直接隐藏loading-box

如果要手动实现加载动画的话,除了一些css代码,核心就是windowload事件;

加载动画能够显示出来,也需要加载并解析它需要的css文件,为了让加载动画尽快显示出来,我们可以选择把这些css代码内联到html文件内,这样渲染加载动画无需等待其他首屏关键css文件,但是我们的博客有许多html页面(每篇文章都是一个独立的html页面),手动内联也太麻烦了…

如果加载动画需要的css代码,是通过link标签引入的,还要等待其他首屏关键css加载解析完毕,才能开始渲染加载动画,也就是说,开始加载css动画了,说明首屏关键css都加载完毕了,可以自己使用3G测试。

修改鼠标样式

修改起来也是很简单的,直接跟着文章敲代码就行。

Hexo鼠标样式修改 | 花猪のBlog

大家也可以自行去查找更多的鼠标样式
上述鼠标样式使用的css文件是网络文件,现在链接好像已经失效了,我们可以选择把鼠标样式图片(.cur文件)下载到本地的themes\butterfly\source\img目录下然后通过绝对路径引入。如果你觉得某个博主的鼠标样式好看,也可以右键检查页面,查看网络日志,获取博主鼠标样式图片的链接然后直接下载到本地。

参考:

hexo+butterfly主题利用css部署网站鼠标指针样式 | JiangnanPsalter

Hexo|Butterfly修改鼠标指针样式 | 珍珠巧克力

SEO优化

提高我们的博客在浏览器中的搜索排名,从而提高我们的博客的曝光量,让更多人看到。

  • 下载插件hexojs/hexo-filter-nofollow: 自动为所有外部链接添加 nofollow 属性。

    通过给博客中引入的外部链接(比如a标签)添加rel="noopener external nofollow noreferrer"属性来优化SEO

    noopener: 防止新打开的页面通过window.opener属性访问原始页面的window对象。

    external: 表示链接指向的是外部网站。

    nofollow: 告诉搜索引擎不要将这个链接视为对目标页面的信任投票;防止页面的链接权重传递给外部网站,有助于保留更多的链接权重;如果你的博客中包含指向低质量或垃圾网站的链接,使用nofollow可以减少这些链接对你的网站造成负面影响的风险。

  • 下载插件Baidu Sitemap generator plugin for Hexo

    下载并配置好后执行hexo g,会自动生成博客的站点地图。需要在百度搜索资源平台注册账号,添加并验证自己的网站,然后提交网站的sitemap.xml(站点地图), 从而提高自己的网站在百度中的SEO

    如果购买的是国外域名,验证可能因超时而失败

  • 下载插件hexojs/hexo-generator-sitemap: Sitemap generator for Hexo.

    下载并配置好后执行hexo g,会自动生成博客的站点地图。然后可以选择去google或者bing的资源平台验证自己的网站并提交站点地图,比较推荐提交到Home - Bing Webmaster Tools,不需要科学上网。

    参考文章:Hexo文章加密 & 搜索引擎优化SEO & 评论系统Twikoo | Yan Zhang’s blog

部署博客到github

部署方法

方法1:可以通过https://[username].github.io的格式来访问部署的资源

  • 仓库名必须为[username].github.io,这样貌似必须通过https://[username].github.io/[username].github.io的方式来访问,其实只需要通过https://[username].github.io的方式来访问就行。

  • 打包产物放到master分支

  • 优点是路径短,更适合用来做博客

方法2:可以通过https://[username].github.io/[repo]的格式来访问部署的资源

  • 可以自定义仓库名
  • 更适合用来展示demo
  • 打包产物放到gh-pages分支

我们使用第一种方式,还要先下载hexo-deployer-git,这个插件的作用如下:

  • 打包后,初次执行hexo deploy时:
    • 在博客根目录下,创建.deploy_git目录,然后拷贝public目录下的所有文件,到这个目录下
    • 初始化.deploy_git目录为git仓库(git init )
    • 根据_config.yml文件,添加远程仓库origin
    • 自动执行git add .git commitgit push -u origin master(分支可自定义)
  • 对于后续hexo deploy操作:
    • 删除.deploy_git目录下除了.git文件的所有文件
    • 拷贝public目录下的所有文件,到这个目录下
    • 然后再执行git add .git commitgit push操作。
  • 总的来说,这个插件的作用就是简化了部署博客时,所需要的git操作,让不懂git操作的小白也能快速部署博客。
1
npm i hexo-deployer-git -D//安装到开发依赖

再在_config.yml文件中进行相关配置

1
2
3
4
deploy:
type: git
repo: https://github.com/shiyuhuiya/shiyuhuiya.github.io.git #写自己的仓库路径
branch: master

然后执行

1
hexo deploy

如果部署失败,可以尝试开启steam++加速github再次部署。

优化方案:因为我们每次修改博客后,重新部署的时候,都要依次执行hexo clean ,hexo g,gulp,hexo deploy,这样未免太繁琐了,其实我们可以在package.json中配置:

1
2
3
4
5
6
"scripts": {
"build": "hexo generate",
"clean": "hexo clean",
"server": "hexo server",
"deploy":"hexo clean && hexo generate && gulp && hexo deploy"
}

之后只需要执行npm run deploy,这四个命令就会自动按顺序串行执行,非常方便。

参考资料:【干货】Luke教你20分钟快速搭建个人博客系列(hexo篇) | 自动化部署在线编辑统统搞定 | 前端必会!_哔哩哔哩_bilibili

但是部署到github pages有一个明显的缺点,就是加载速度很慢。为什么加载速度很慢呢?因为github pages服务器在国外,离我们较远;距离越远,意味着要经过越多的网络结点,每个节点都会引入额外的延迟,遇到网络拥塞的概率也越大。

自定义github域名

为了能让我们的域名更有个性(不会提高网站的加载速度),我们可以选择自定义域名,这需要我们购买域名;域名购买国内国外的都可以,只要域名解析后对应的服务器不是中国境内的,就不需要备案。可参考国内域名一定要备案吗? - 知乎

国外域名购买流程比较简单,比较推荐的是namesilo

Namesilo 域名购买及使用教程(附 Namesilo 优惠码) - 知乎

购买域名后,我们就能自定义我们的域名的dns解析方式;打开域名管理,在我们的域名下添加一条CNAME类型的dns记录,让对自定义域名的解析转变成对用户名.github.io域名的解析

具体域名解析方式已经在《前端面试---网络》一文中介绍,下面只给出几幅图(省略了本地dns服务器递归查询缓存的过程)。

未自定义域名前的请求流程

自定义域名后的请求简化流程,比如我在namesilo网站上购买了sanye.blog这个域名,并在我的域名的dns解析记录下添加一条CNAME记录,让对域名www.sanye.blog域名的解析指向用户名.github.io域名的解析

拿到ip后访问对应的githubpages服务器,请求中携带的hostwww.sanye.blog,因为我们在github上配置了,所以github知道对应的默认域名,然后就从默认域名中提取出用户名,根据用户名返回对应的资源。

添加自定义域名后,对原域名的访问也会重定向到自定义域名。在你的 GitHub Pages 仓库中,GitHub 会生成或更新一个名为 CNAME 的文件,其中包含你的自定义域名(例如 www.sanye.blog)。这个文件告诉 GitHub 你的站点应该通过哪个自定义域名访问。

建议在github pages中开启enfore https这样直接访问自定义域名也不会以http协议加载,而是强制用https协议访问,不会出现“网站不安全”的警告。

具体步骤参考文章:

Github 部署个人网页 | 自定义域名 - 知乎Github 部署个人网页 | 自定义域名 - 知乎

上述这篇文章“购买国内域名就要备份的说法是不准确的”

搞懂自定义域名 - 知乎

然而我并不建议给github pages自定义域名🤣,因为即便自定义了域名,也不会提高我们博客的访问速度,因为我们的博客还是部署在github服务器上的,访问速度还是很慢,为什么要浪费宝贵的域名呢

因为我们是给[用户名].github.io这个仓库自定义域名,这就意味着对[用户名].github.io这个域名的解析都会重定向到我们自定义的域名,这就导致,其他仓库,原本的访问url格式是,https://[username].github.io/[repo]即便不自定义域名,也会被重定向到https://自定义域名/[repo],所以最好还是把博客,迁移到vercel,然后给vercel服务器上的项目自定义域名,参考下文。

如何提高博客的加载速度

  • 我们可以选择把我们的博客部署到其他平台。

    参考使用第三方托管平台部署博客 | Akilarの糖果屋;这篇文章介绍了其他的博客部署平台,
    gitee:国内网站,但是目前pages功能停用了,除此之外还有其他问题;

    Netlify:国外网站,免费,但是注册麻烦,需要hotmail或者gmail等国外常用邮箱,一顿操作下来发现还是白忙活🥲;

    webify:腾讯的产品,要money,没有尝试过;

    vercel:重点介绍。

  • 打包静态资源

    打包html,js,css

    参考文章:使用gulp压缩博客静态资源 | Akilarの糖果屋

    执行hexo g指令后,我们可以看到public文件夹中生成了一系列的静态文件,比如html,css,js这些文件的内容格式是非常容易阅读的,显然,他们是未经过压缩的,我们可以借助打包工具gulp,实现对这些静态资源的打包,然后再部署到网站上去,能在一定程度上提高我们博客的加载速度。

    • 安装Gulp插件:在博客根目录[Blogroot]打开终端,输入:

      1
      2
      npm install --global gulp-cli #全局安装gulp指令集
      npm install gulp --save #安装gulp插件
    • 安装各个下属插件(安装到开发环境),以实现对各类静态资源的压缩:

      • 压缩HTML:

        1
        2
        3
        4
        npm install gulp-htmlclean --save-dev

        # 用gulp-html-minifier-terser可以压缩HTML中的ES6语法
        npm install gulp-html-minifier-terser --save-dev
      • 压缩CSS:

        1
        npm install gulp-clean-css --save-dev
      • 压缩js:

        1
        npm install gulp-terser --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
      50
      51
      52
      //用到的各个插件
      var gulp = require('gulp');
      var cleanCSS = require('gulp-clean-css');
      var htmlmin = require('gulp-html-minifier-terser');
      var htmlclean = require('gulp-htmlclean');
      // gulp-tester
      var terser = require('gulp-terser');
      // 压缩js
      gulp.task('compress', () =>{
      // './public/**/*.js'表示从当前目录下的public文件夹开始,匹配所有子目录(后代目录)中的.js文件
      // '!./public/**/*.min.js'是一个否定模式,意味着排除所有已经带有.min.js扩展名的文件
      gulp.src(['./public/**/*.js', '!./public/**/*.min.js'])
      .pipe(terser())
      .pipe(gulp.dest('./public'))
      //压缩后的js文件将会被放置回public文件夹下。
      //注意,这会覆盖原有的非最小化版本的js文件,除非你在前面的步骤中对文件进行了重命名(例如添加.min后缀),
      //以便与原始文件区分开来。
      });
      //压缩css
      gulp.task('minify-css', () => {
      return gulp.src(['./public/**/*.css'])
      .pipe(cleanCSS({
      compatibility: 'ie11'
      }))
      .pipe(gulp.dest('./public'));
      });
      //压缩html
      gulp.task('minify-html', () => {
      return gulp.src('./public/**/*.html')
      .pipe(htmlclean())
      .pipe(htmlmin({
      removeComments: true, //清除html注释
      collapseWhitespace: true, //压缩html
      collapseBooleanAttributes: true,
      //省略布尔属性的值,例如:<input checked="true"/> ==> <input />
      removeEmptyAttributes: true,
      //删除所有空格作属性值,例如:<input id="" /> ==> <input />
      removeScriptTypeAttributes: true,
      //删除<script>的type="text/javascript"
      removeStyleLinkTypeAttributes: true,
      //删除<style>和<link>的 type="text/css"
      minifyJS: true, //压缩页面 JS
      minifyCSS: true, //压缩页面 CSS
      minifyURLs: true //压缩页面URL
      }))
      .pipe(gulp.dest('./public'))
      });
      //注册一个名为'default'的任务。这个任务将会并行运行三个子任务:'compress'、'minify-css'和'minify-html'。
      //然后在控制台执行gulp,就会默认执行default任务
      gulp.task('default', gulp.parallel(
      'compress', 'minify-css', 'minify-html'
      ))

      上述代码中用到了一些gulp的api:

      • gulp.task:第一个参数传入任务名,第二个参数传入一个函数,指明任务内容
      • gulp.src:传入一个数组,数组中的元素是文件路径,指定要处理哪些文件,经常作为gulp压缩流程的起点
      • gulp.dest:传入文件输出路径,通常作为gulp压缩流的终点,传入最后一个pipe()操作中
      • gulp.parallel:Gulp 4.x版本引入的一个新特性,它允许指定一组任务以并行方式执行。

    打包图片

    其实官方文档Butterfly 文檔(六) 進階教程 | Butterfly也提供了相关的打包方法,本质就是对本地的图片压缩后再使用,减小图片体积。

  • cdn加速

    cdn加速在《前端面试—网络》一文中以及介绍过了,不赘述。

    这里谈谈如何如何给国外域名使用CDN加速

    可参考文章:Github 部署 | CDN 加速网页,速度嗖嗖的快! - 知乎

    这篇文章其实还是有问题的,虽然腾讯云能给国外域名提供cdn加速,但是加速区域只能选择国外,加速国内就要求域名备份(当然国内域名开通CDN加速也要备份),也就是说,我们在源服务器(github pages服务器)上的部署的博客文件只能被国外的cdn服务器缓存,对在国内访问网站的加载速度的提高并不明显,而且开通cdn加速后还要自己给自定义域名申请ssl证书(因为存储我们博客的cdn服务器需要ssl证书,才能以https协议访问),这个过程还要验证域名,而且不知道为什么一直通过不了验证,干脆放弃……

    使用腾讯云给我们的域名接入cdn加速后,会得到一个CNAME,然后我们在我们的域名的dns记录上添加对应的CNAME记录即可。

    还有就是在上面的文章中,给我们的国外域名加速,给cdn服务器配置的源站地址github pages服务器的四个ip地址,查阅资料后发现,其实源站地址指定为用户名.github.io这个域名也是可行且容易理解的,所有形如用户名.github.io的域名都只会被解析到这4个ip地址中的一个也就是说这4个ip可以对应多个域名一个域名也能对应不止一个ip地址,这些 IP 地址通常指向相同的资源。具体来说,这些 IP 地址背后的服务器存储的资源是相同的,但它们可能分布在不同的地理位置或数据中心,以实现负载均衡和提高可用性

    在阅读butterfly文档的过程中发现竟然提供了cdn加速的方案?了解之后发现是一些国内的网站,主动给一些国外的常用的前端资源提供了cdn加速,并免费提供访问的cdn链接,然而我们的博客生成静态资源显然是享受不到的这种免费的cdn加速的。但是如果你使用到了某些外部链接,可以考虑把他们替换为经过cdn加速的链接 ,从而提高博客加载速度。

    总之给部署在github上的博客接入CDN加速是一件很麻烦的事情,其实用vercel部署自己的博客访问速度其实也很nice了,因为vercel提供了免费的cdn服务。

Vercel

账号注册

注册账号简单且免费,直接使用github账号登录即可,在国内的访问速度也比github pages要快,并且何以导入git仓库,部署起来非常方便,后续在对应仓库中推送新的提交也会自动部署,省心省力。

部署步骤可参考文章:如何使用 Vercel 部署自己的 Hexo 博客_vercel部署博客-CSDN博客

自定义域名

在Vercel上部署好静态站点之后,会获得哦一个自动分配的域名,以vercel.app结尾,就像githubpages也会给默认域名一样,不幸的是,这个域名被dns污染了(被墙了),有人不想我们这么简单就能访问这个网站,我们无法通过这个自动分配的域名,访问到我们的项目;但是我们还是有解决办法的,比较推荐的就是自定义域名,按照提示操作即可,又不幸的是,自定义域名使用到的cname-vercel-dns.com也存在被dns污染的问题,对此网上常见的解决办法是把cname-vercel-dns.com替换成固定的ip值,或者替换成cname-china.vercel-dns.com,还有一种方法是借助cloudfare,把对cname-vercel-dns.com的解析工作交给cloudfare,这个工作默认是你购买的域名的服务商提供的。

个人猜测:如果购买的是国内的域名,使用的就是国内提供的dns解析服务,就存在被墙的风险,所以推荐购买国外域名,使用国外的dns解析服务,也许就不会有这个问题,至少博主使用国外的域名暂时没遇到什么问题

可参考文章:Vercel部署个人静态之DNS污染劫持问题_vercel dns-CSDN博客

其中裸域名(根域名)比如sanye.blog指向的是76.76.21.21,我们直接访问这个ip,就等同于登录vercel

其中www.sanye.blog指向的是cname-vercel-dns.com或者76.223.126.88,也等同于直接登录vercel

自动打包

然后其实我们可以直接把项目的源码(比如vue项目)忽略掉node_modules目录后,push到github对应的仓库中去,然后再部署到vercel上去,vercel一般会自动识别vue项目,vercel 在部署时会执行以下步骤:

  1. 克隆代码:从 GitHub 仓库中拉取代码。
  2. 安装依赖:根据配置文件运行 npm installyarn install
  3. 构建项目:运行指定的构建命令(如 npm run build)。
  4. 部署静态文件:将构建后的静态文件部署到其全球 CDN。

从这一点出发的话,其实我们不需要借助hexo-deployer-git来部署我们的项目,因为这个工具只会将我们build后,生产的public文件下的资源部署到github对应的仓库上,这就要求我们手动进行打包(hexo g)。

支持history路由

我们知道,使用history路由的项目是需要后端配合的,但是我们项目部署的位置是vercel服务器,该如何让其配合我们呢?

Vercel 提供了一个简单的配置文件 vercel.json,可以用来指定如何处理路由。以下是一个示例配置:

1
2
3
4
5
6
7
8
{
"routes": [
{
"src": "/(.*)",
"dest": "/index.html"
}
]
}
  • 解释
    • src: "/(.*)":匹配所有的路径。
    • dest: "/index.html":将所有请求重定向到 index.html 文件。
    • 这样,无论用户访问什么路径,Vercel 都会返回 index.html,让前端路由接管。
  • 操作步骤
    1. 在项目的public目录下创建一个名为 vercel.json 的文件(确保打包后vercel.json 文件会在根目录的位置)。
    2. 将上述内容复制到文件中。
    3. 部署项目到 Vercel。

当然我们的博客项目并不需要使用history路由,因为我们的博客项目是多页面应用程序

根据项目部署的位置不同,上述json文件可能也需要做适当的修改,不过无论如何, vercel.json都应该放到服务器的根目录下,下面分享一下我部署项目编写的json文件:

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
{
"routes": [
{
// 所有以/bigEvent/assets/开头的请求都会被这个规则处理,而(.*)部分则捕获了/bigEvent/assets/之后的所有字符
"src": "/bigEvent/assets/(.*)",
// 使用$1来引用前面捕获组中的内容,如果请求是/bigEvent/assets/index.js,则$1就是index.js
"dest": "/bigEvent/assets/$1"
},
{
"src": "/bigEvent/favicon.ico",
"dest": "/bigEvent/favicon.ico"
},
{
"src": "/bigEvent/(.*)",
"dest": "/bigEvent/index.html"
},
{
"src": "/rabbit/assets/(.*)",
"dest": "/rabbit/assets/$1"
},
{
"src": "/rabbit/favicon.ico",
"dest": "/rabbit/favicon.ico"
},
{
"src": "/rabbit/(.*)",
"dest": "/rabbit/index.html"
}
]
}

优化加载速度

1
2
3
4
5
6
7
8
//_config.butterfly.yml
CDN:
# The CDN provider for internal and third-party scripts
# Options for both: local/jsdelivr/unpkg/cdnjs/custom
# Note: Dev version can only use 'local' for internal scripts
# Note: When setting third-party scripts to 'local', you need to install hexo-butterfly-extjs
internal_provider: local
third_party_provider: local

我们可以通过下载hexo-butterfly-extjs

1
npm i hexo-butterfly-extjs

并配置third_party_providerlocal,然后我们加载一些第三方的cssjs文件就不需要通过cdn了,因为我们已经把这些第三方文件下载到了本地,我们打包后,可以观察到public目录下多出了pluginsSrc目录。

按照上述的步骤配置后,我们就能明显的发现,开发和生产过程中,网站的加载速度变快了许多。

但是当我们部署博客的时候,发现出错了,并提示”路径 pluginsSrc/twikoo/dist/twikoo.all.min.js:2 存在一个 Tencent Cloud Secret ID”,因为GitHub 实施了一项名为“Push Protection”的安全功能,它会扫描你的提交以防止意外泄露敏感信息(例如 API 密钥、密码等)。在这个案例中,系统发现了 Tencent Cloud Secret ID,并阻止了这次推送。

所以怎么办?我们先cd.deploy_git,执行git reset --hard <上一次提交的哈希值> ,撤销这次包含敏感信息的提交(还有一种方法,就是直接删除.deploy_git目录,不过这样你之前的提交记录都没了),然后由于我们每次打包后,public目录下都会包含这个twikoo.all.min.js文件,所以我们需要自动删除它。

source目录下新建del.js文件:

1
2
3
4
5
6
7
8
const fs = require('fs');
const path = require('path')
try {
fs.unlinkSync(path.join(__dirname,'pluginsSrc/twikoo/dist/twikoo.all.min.js'));
console.log('文件删除成功');
} catch (err) {
console.error('文件删除失败:', err);
}

然后这个文件就会被打包到public目录的根目录下。

然后我们还要修改一下部署指令,每次部署的时候,自动删除这个文件

1
2
3
4
5
6
7
"scripts": {
"build": "hexo generate",
"clean": "hexo clean",
"server": "hexo server",
"del": "node ./public/del.js",
"deploy": "hexo clean && hexo generate && npm run del && gulp && hexo deploy"
},

感想与结语

hexo+butterfly框架能帮助我们迅速开发一个美观实用的博客,这些框架,主题,以及相关插件的诞生,基于开发者雄厚的html,css,js等前端知识积累;做为刚入们的前端开发者,我也知道给光看文档能学到的实在是有限,在网上找资料学到的也是偏向实践,想要深入了解原理,自己做出这些效果,还得多学多练,打好自己前端基础。

如果你还想进一步美化自己的博客,给自己的博客添加更多的功能,你可以选择不断的阅读butterfly官方文档,也可以去网上查找更多的资料,以下是我推荐的一些资料,希望能帮助到你。