什么是hexo?
Hexo 是一个快速、简洁且高效的博客框架。 Hexo 使用 Markdown
(或其他标记语言)解析文章,在几秒内,即可利用靓丽的主题生成静态网页(html)。
其他博客框架:vuepress , gatsby;前者适合vue开发者,后者适合react开发者。
安装hexo
需要提前准备的工具:vscode, git, node.js;去对应的官网下载即可。
在任意位置新建一个文件夹,右键选择用vscode打开;或者直接打开vscode新建一个文件夹,取一个合适的名字,比如blog;右键文件夹,在当前文件下打开终端,执行以下命令:
1 | npm install -g hexo-cli //全局安装hexo |
好了,再访问http://localhost:4000
就能看到运行在本地的博客了
hexo常用指令
1 | hexo clean //用于清理由 Hexo 生成的缓存文件和静态文件(public文件) |
项目结构分析
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 | # URL |
修改博客分享方式
1 | share: |
新建分类
为了方便我们博客文章的查找,我们很自然的会想到给博客分类,执行如下命令:
1 | hexo new page categories //本质是在创建一个页面page |
你会找到source/categories/index.md
这个文件
修改这个文件的Front-Matter
部分:
1 | title: 分类 |
然后我们在每篇博客的Front-matter
部分就可以通过categories
属性给文章分类。示例:categories: 'book'
注意:如果我们未创建分类页面,点击分类标签是会报错的,提示找不到该页面。
之后我们点击’分类’,就可以成功跳转到分类页面,但是,我们可以观察到,分类页没有顶部图片,是纯蓝色,不够美观,其实我们只要在source/categories/index.md
的Front-matter
部分添加一个top_img
属性,指定顶部图片的路径即可。
1 |
|
新建标签
我们还可以给每篇文章添加多个标签,执行如下命令:
1 | hexo new page tags //本质也是在创建一个页面page |
你会找到source/tags/index.md
这个文件
修改这个文件的Front-Matter
部分:
1 | title: tags |
然后我们在每篇博客的Front-matter
部分就可以通过tags
属性给文章添加标签,一篇文章可以添加多个标签,示例:
1 | //要注意缩进,否则可能报错 |
注意:如果我们未创建tags页面,点击tags标签是会报错的,提示找不到该页面。
给tags页面添加top_img
的方法同上文
新建图库
新建图库的原理和新建分类,标签的原理是相同的,都是新建一个页面
1 | hexo new page gallery |
你会找到source/gallery/index.md
这个文件,这个文件的内容如下:
1 | <div class="gallery-group-main"> |
name
:图库名字description
:图库描述link
:连接到对应相册的地址img-url
:图库封面的地址
举个例子:
1 | --- |
top_img: false
,的作用是禁用gallery
页面的顶部图片。
然后在source/gallery
目录下新建其他文件夹,代表不同的图库,比如mqm
,然后在这个目录下新建index.md
文件
1 | --- |
aside: false
的作用是关闭gallery/mqm
页面下的侧边栏
为了让页面更美观,可以引用一个background.js
文件:
1 | const wrap = document.querySelector('#body-wrap') |
1 | @keyframes scroll { |
新建视频播放器
其实有了前面几个新键页面的基础,新建一个视频播放页面也是比较简单的,不过这里有几个需要注意的地方
在不使用
top_img
的情况下,会使用title
来替代,为了方便,我们在所有title
上都添加返回图标所有视频共用一个播放页面,通过查询参数判断播放什么视频
github上可存储的文件大小不能超过
100mb
,所以不能上传太大的视频,vercel也是。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20if (/\/animeClips\/play/.test(location.pathname)) {
//使用URLSearchParams,能很快的从查询参数中取值,前提是你知道有哪些参数
const urlParams = new URLSearchParams(location.search)
const title = urlParams.get('title')
const video = urlParams.get('video')
document.addEventListener('DOMContentLoaded', () => {
const v = document.querySelector('#article-container video')
v.src = `/animeClips/video/${video}.mp4`
//支持自定义标题
document.querySelector('.page-title').innerHTML = `<i class="fa-solid fa-arrow-left" onclick="history.go(-1)"></i>${title ? title : video}`
})
}else{
//给标题部分添加返回按钮,使用于所有不使用top_img的页面
const title = document.querySelector('.page-title')
if(title){
let a = title.innerHTML
title.innerHTML = `<i class="fa-solid fa-arrow-left" onclick="history.go(-1)"></i>`+a
}
}视频播放主要依赖的是
video
标签,添加controls
属性,才能显示交互栏。当浏览器请求一个大文件(如视频或音频)时,为了支持播放器的“拖动进度条”功能,浏览器通常会发送带有
Range
字段的 HTTP 请求1
2
3GET /video.mp4 HTTP/1.1
Host: example.com
Range: bytes=1024-2048 //这表示客户端希望获取文件从第 1024 到 2048 字节之间的内容。服务器在响应中可以通过
Accept-Ranges
头告诉客户端它是否支持范围请求。1
2
3
4HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Range: bytes 1024-2048/1000000
Content-Length: 1025如果服务器返回
Accept-Ranges: bytes
,表示它支持按字节范围请求资源,此时:- 浏览器可以并行加载多个片段,提高加载效率;
- 用户可以拖动进度条跳转到任意位置开始播放;
- 拖动后会触发新的
Range
请求。
如果没有这个字段,或者返回的是
none
,表示服务器不支持分段请求,此时:- 即使首次请求使用了
Range
,服务器也会忽略该字段,返回整个文件; - 后续拖动进度条时,浏览器知道服务器不支持分段加载,因此不会发起新请求;
- 播放器可能会禁用拖动功能,或者拖动后自动回正(因为无法加载目标位置的数据);
在hexo开发环境下,无法拖动进度条,而且拖动进度条不会发送请求,因为使用的是hexo搭建的服务器,无法设置
Accept-Ranges: bytes
响应头,但是当我们把视频放到vercel上,就没问题了为了优化视频加载,给video标签添加
preload='auto'
属性,提示浏览器尽可能多地预加载视频数据。如果服务器支持,并且用户网络条件允许,这将使得视频能够更快地开始播放,并允许用户随意拖动进度条到未缓冲部分。
其实如果我们在b站上发布视频,也可以直接嵌入到我们的页面中来,在分享的时候选择”嵌入代码”,即可,本质是使用了iframe
标签。
参考视频:Hexo插入响应式Bilibili视频代码块 | 花猪のBlog
自定义主页
博客的主页就是博客的首页,如下:

自定义主页的详细内容见官方文档Butterfly 文檔(三) 主題配置 | Butterfly,下面我只介绍我遇到困难的部分。
自定义菜单
在_config.butterfly.yml
文件中设置:
1 | menu: |
当然这些都是我认为最基础的菜单设置,||
前面的表示的是页面的路径,后面表示的是图标。
在自定义这部分的时候我遇到了一个问题,就是无论如何配置,菜单上都会有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 | search: |
更多搜索方式参考文章:Hexo + Butterfly 键入搜索功能 - 简书以及butterfly官方文档
自定义首页图片
1 | # 禁用顶部图片 |
这三个配置项默认并不在一起,但是我为了方便配置把它们放到了一起。
引入图片
通过网络图片的形式引入
优点:减小打包体积
缺点:博客部署在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 | social: |
书写格式 图标名:url || 描述性文字 || color
图标名可在这个网站上查找:fontawesome,找到满意的图标直接使用即可,甚至不需要下载,非常方便。
统计网站访客数目
我们的博客是纯静态网页,没有涉及到与后端的数据交互,但是我们如果想要实现统计网站访客数目的功能,就必须借助后端,那该怎么实现呢?幸运的是,有人愿意免费给我们提供服务器来存储我们网站的访客数据。
不蒜子 - 极简网页计数器 是一个轻量级的网站访问统计工具,它通过简单的 JavaScript 代码嵌入到网页中来实现访问次数的统计。
大致原理
当用户访问包含 Busuanzi 脚本的页面时,该脚本会在用户的浏览器上执行,然后发送一个jsonp请求,请求头中的Referer
字段会携带当前网站的url
,busuanzi服务器会从Referer
字段中,提取出网站的域名等信息,并将该域名对应的网站访问次数加1,再返回一串js代码,这串代码是一段函数执行的代码,传入函数的实参就包含了网站被访问次数等信息,然后浏览器会执行这串代码,把返回的信息渲染到页面上。具体原理参考源码。
如官网所示,我们只需在网页中引入一个js文件就行,对于butterfly主题的hexo博客,用上这个工具更是简单,我们只需要在主题配置文件中启用这个插件就行:
1 | busuanzi: |
1 | # 确保开启webinfo,不然也不会显示访客数据 |
博客网站访客量虚高的原因。
我们的博客部署在本地localhost:4000,大家都用这个域名测试博客,访客量当然特别高了,部署到自己的网站后就没问题了。
我们的博客网站所在域名之前可能已经使用过busuanzi提供的服务了,但是无论我们是按照官网的指示直接引入js文件,还是在butterfly的主题配置文件中开启相关配置,请求获取的都是官方的js文件,也就是源码,我们可以通过直接在浏览器导航栏输入官方js文件的网址(在官网已给出),从而下载,修改源码来解决这个问题。我们把下载好的源码放在
themes/butterfly/source/js目录
下,并在源码中做如下修改:
1 | // 我们先分析这三个字段什么意思 |
然后在主题配置文件中修改busuanzi的默认cdn链接,指定为本地文件。
1 | CDN: |
当然,如果我们的博客因为部署的域名改变了,需要加上先前的访问次数,也可以使用这种方式来实现。
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 | footer: |
加载动画
如果我们的博客部署在GitHub,或者我们的博客打开需要加载较多的网络资源,就会导致我们的博客打开很慢,这个时候通过加入加载动画就能优化读者的阅读体验。
修改步骤
butterfly主题提供了默认的加载动画,但是可能不够美观,这时候我们就可以根据自己的喜好自定义了。
自定义loading的大概步骤:
- 修改
loading.pug
- 修改
loading.styl
参考文章:多种加载动画
我在做自己的博客的时候,并没有完全跟着博客敲代码,而是先大致了解一下代码的逻辑,然后只选择了其中的一种加载动画—钢铁之心,所以省去了很多步骤,如果不喜欢加载完成后展开的过渡效果的,可以对source/css/_layout/loading.styl
文件做如下修改:
1 | &.loaded |
意思就是,页面加载完毕之后,直接隐藏loading-box
。
原理分析
如果要手动实现加载动画的话,除了一些html,css代码,核心就是window
的load
事件:load事件触发后,移除loading
。
加载动画能够显示出来,也需要加载并解析它需要的css文件,我们能看到loading
,说明对应的css文件加载完毕了,且首屏已经渲染了。
为了让加载动画尽快显示出来,我们可以选择把这些css代码内联到html文件内,这样渲染加载动画(loading)无需等待其他首屏关键css文件,但是我们的博客有许多html页面(每篇文章都是一个独立的html页面),手动内联也太麻烦了…
如果加载动画需要的css代码,是通过link标签引入的,还要等待其他首屏关键css加载解析完毕,才能开始渲染加载动画,也就是说,开始加载css动画了,说明首屏关键css都加载完毕了,可以自己使用3G测试。
修改鼠标样式
本质就是修改某个dom元素的样式属性,CSS中的cursor
属性,用于定义鼠标指针悬停在元素上时显示的光标类型(形状),以提供视觉反馈,增强用户体验
通用类型:
default
:默认箭头pointer/hand
:手形(用于链接)text
:工字梁(文本选择)move
:十字箭头(可拖动)wait/progress
:沙漏(等待状态)
特殊状态:
not-allowed
:禁止操作help
:问号(帮助信息)
自定义样式:通过
url()
指定图片(格式需为.cur
或.ani
),并设置备用值1
cursor: url('custom.cur'), pointer;
参考下面文章:Hexo鼠标样式修改 | 花猪のBlog
大家也可以自行去查找更多的鼠标样式,上述鼠标样式使用的.cur
文件是cdn链接,现在链接好像已经失效了,我们可以选择把鼠标样式图片(.cur文件),下载到本地的themes\butterfly\source\img
目录下,然后通过绝对路径引入。如果你觉得某个博主的鼠标样式好看,也可以右键检查页面,查看网络日志,获取博主鼠标样式图片的链接然后直接下载到本地。
参考:
hexo+butterfly主题利用css部署网站鼠标指针样式 | JiangnanPsalter
Hexo|Butterfly修改鼠标指针样式 | 珍珠巧克力
SEO优化
提高我们的博客在浏览器中的搜索排名,从而提高我们的博客的曝光量,让更多人看到。不过使用hexo搭建的博客是多页面应用程序,所以本身的seo就不错。
给a标签添加rel属性
下载插件hexojs/hexo-filter-nofollow: 自动为所有外部链接添加 nofollow 属性。
通过给博客中引入的外部链接(比如a标签)添加rel="noopener external nofollow noreferrer"
属性来优化SEO
noopener: 防止新打开的页面通过window.opener
属性访问原始页面的window
对象。
external: 表示链接指向的是外部网站。
nofollow: 告诉搜索引擎不要将这个链接视为对目标页面的信任投票;防止页面的链接权重传递给外部网站,有助于保留更多的链接权重;如果你的博客中包含指向低质量或垃圾网站的链接,使用nofollow
可以减少这些链接对你的网站造成负面影响的风险。
提交站点地图到资源搜索平台
下载并配置好后执行hexo g
,会自动生成博客的站点地图。需要在百度搜索资源平台注册账号,添加并验证自己的网站,然后提交网站的sitemap.xml(站点地图), 从而提高自己的网站在百度中的SEO,如果购买的是国外域名,验证可能因超时而失败。
下载插件hexojs/hexo-generator-sitemap: Sitemap generator for Hexo.
下载并配置好后执行
hexo g
,会自动生成博客的站点地图。然后可以选择去google或者bing的资源平台,验证自己的网站并提交站点地图,比较推荐提交到Home - Bing Webmaster Tools,不需要科学上网。
部署博客到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 commit
和git push -u origin master(分支可自定义)
- 在博客根目录下,创建
- 后续博客更新,再次打包后,执行
hexo deploy
操作:- 删除
.deploy_git
目录下除了.git
文件的所有文件 - 拷贝
public
目录下的所有文件,到这个目录下 - 然后再执行
git add .
,git commit
和git push
操作。
- 删除
- 总的来说,这个插件的作用就是简化了部署博客时,所需要的
git
操作,让不懂git
操作的小白也能快速部署博客。
1 | npm i hexo-deployer-git -D//安装到开发依赖 |
再在_config.yml
文件中进行相关配置
1 | deploy: |
然后执行
1 | hexo deploy |
如果部署失败,可以尝试开启steam++
加速github再次部署。
优化方案:因为我们每次修改博客后,重新部署的时候,都要依次执行hexo clean ,hexo g,gulp,hexo deploy
,这样未免太繁琐了,其实我们可以在package.json
中配置:
1 | "scripts": { |
之后只需要执行npm run deploy
,这四个命令就会自动按顺序串行执行,非常方便。
参考资料:【干货】Luke教你20分钟快速搭建个人博客系列(hexo篇) | 自动化部署在线编辑统统搞定 | 前端必会!_哔哩哔哩_bilibili
但是部署到github pages有一个明显的缺点,就是加载速度很慢。为什么加载速度很慢呢?因为github pages服务器在国外,离我们较远;距离越远,意味着要经过越多的网络结点,每个节点都会引入额外的延迟,遇到网络拥塞的概率也越大。
自定义github域名
域名购买
为了能让我们的域名更有个性
(不会提高网站的加载速度),我们可以选择自定义域名,这需要我们购买域名;域名购买国内,国外的都可以,只要域名解析后对应的服务器不是中国境内的,就不需要域名备案。
购买国内域名的优缺点:
- 必须进行实名认证,即便解析后对应的服务器不在国内
- 进入控制台的速度较快,管理DNS记录方便
- 支持域名备案
购买国外域名的优缺点:
- 不需要进行实名认证,比较推荐的是namesilo
- 进入控制台加载速度较慢,对网络速度要求较高
- 无法进行域名备案
个人还是推荐购买国内的域名!
添加DNS记录
购买域名后,我们就能自定义我们的域名的dns解析方式;打开域名管理,在我们的域名下添加一条CNAME
类型的dns记录,让对自定义域名
的解析转变成对用户名.github.io
域名的解析
具体域名解析
方式已经在《前端面试---网络》
一文中介绍,下面只给出几幅图(省略了本地dns服务器递归查询缓存的过程)。
请求流程对比
未自定义域名前的请求流程

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

拿到ip
后,访问对应的githubpages
服务器,请求中携带的host
是www.sanye.blog
,因为我们在github上配置了,所以github
知道对应的默认域名
,然后就从默认域名
中提取出用户名
,根据用户名
返回对应的资源。
添加自定义域名后,对原域名的访问,也会重定向
到自定义域名:在你的 GitHub Pages 仓库中,GitHub 会生成或更新一个名为 CNAME
的文件,其中包含你的自定义域名(例如 www.sanye.blog
)。这个文件告诉 GitHub 你的站点,应该通过哪个自定义域名访问。
建议在github pages中开启enfore https,这样
直接访问自定义域名
也不会以http协议加载,而是强制用https协议访问,不会出现“网站不安全”的警告。
具体步骤参考文章:
Github 部署个人网页 | 自定义域名 - 知乎Github 部署个人网页 | 自定义域名 - 知乎
上述这篇文章“购买国内域名就要备份的说法是不准确的”
出现的问题
1 | 因为我们是给`[用户名].github.io`这个仓库自定义域名, |
然而我并不建议给github pages自定义域名🤣,因为即便自定义了域名,也不会提高我们博客的访问速度,因为我们的博客还是部署在github服务器上的,访问速度还是很慢,为什么要浪费宝贵的域名呢。
如何提高博客的加载速度
部署博客到其他平台
参考使用第三方托管平台部署博客 | Akilarの糖果屋;这篇文章介绍了其他的博客部署平台,
gitee:国内网站,但是目前pages功能停用了,除此之外还有其他问题;
Netlify:国外网站,免费,但是注册麻烦,需要hotmail或者gmail等国外常用邮箱,一顿操作下来发现还是白忙活🥲;
webify:腾讯的产品,要money,没有尝试过;
vercel:后续重点介绍。
打包静态资源
压缩js,css,html
参考文章:使用gulp压缩博客静态资源 | Akilarの糖果屋
执行hexo g
指令后,我们可以看到public文件夹中生成了一系列的静态文件,比如html,css,js
这些文件的内容格式是非常容易阅读的,显然,他们是未经过压缩的,我们可以借助打包工具gulp,实现对这些静态资源的打包,然后再部署到网站上去,能在一定程度上提高我们博客的加载速度。
安装Gulp插件:在博客根目录
[Blogroot]
打开终端,输入:1
2npm install --global gulp-cli #全局安装gulp指令集
npm install gulp --save #安装gulp插件安装各个下属插件(安装到开发环境),以实现对各类静态资源的压缩:
压缩HTML:
1
2
3
4npm 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,在《前端面试—网络》一文中以及介绍过了,不赘述。、
参考这篇文章:Github 部署 | CDN 加速网页,速度嗖嗖的快! - 知乎
1 | 在上面的文章中,给我们的域名加速,给`cdn服务器`配置的`源站地址`,是`github pages`服务器的四个ip地址, |
总结下cdn加速有几个需要注意的地方:
接入cdn加速要money
接入cdn加速,加速的是某个域名,必须提供域名,cdn加速在这个域名的解析过程中生效:给我们的域名接入cdn加速后,会得到一个加速域名,这个加速域名解析后,返回的是最合适的CDN服务器的ip地址,我们只需在我们域名的
dns记录
上,添加对应的CNAME
记录,指向这个加速域名即可。我们的博客可能部署在vercel或者GitHub,也就是说
源服务器
都不在国内,所以我们不需要给域名备案,而接入cdn加速就是要国内的cdn服务器拷贝我们的博客资源,这就要求我们的域名进行备案如果我们购买的是国外的域名,则无法进行备案,必须购买国内的域名。
给域名备案,必须指定对应的服务器地址,在阿里云备案,必须指定阿里云自家的云产品实例,也就是说我们还要买一个阿里云服务器才能给域名备案,既然都买国内服务器了,为什么不把博客直接部署到国内的服务器呢?如果我们博客本身就部署在国内,其实都不需要考虑接入cdn服务,也能有不错的访问速度。
所以考虑给部署在国外的博客接入国内的CDN,还不如在国内购买一台服务器。
不过把自己的博客部署到服务器,使之能正常被访问也是要花时间的,毕竟服务器本质和我们的电脑没啥区别。
在阅读butterfly文档的过程中发现竟然提供了cdn加速的方案?了解之后发现是一些国内的网站,主动给一些国外的常用的前端资源提供了cdn加速,并免费提供访问的cdn链接,然而我们的博客生成静态资源,显然是享受不到的这种免费的cdn加速的。但是如果你使用到了某些外部链接,可以考虑把他们替换为经过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 在部署时会执行以下步骤:
- 克隆代码:从 GitHub 仓库中拉取代码。
- 安装依赖:根据配置文件运行
npm install
或yarn install
。 - 构建项目:运行指定的构建命令(如
npm run build
)。 - 部署静态文件:将构建后的静态文件,部署到其全球 CDN(当然不包括国内)。
从这一点出发的话,其实我们不需要借助hexo-deployer-git
来部署我们的项目,因为这个工具只会将我们build
后,生产的public
文件下的资源部署到github对应的仓库上,这就要求我们手动进行git
版本管理。
支持history路由
我们知道,使用history路由的项目是需要后端配合的,但是我们项目部署的位置是vercel服务器,该如何让其配合我们呢?
Vercel 提供了一个简单的配置文件 vercel.json
,可以用来指定如何处理路由。以下是一个示例配置:
1 | { |
- 解释:
src: "/(.*)"
:匹配所有的路径。dest: "/index.html"
:将所有请求重定向到index.html
文件。- 这样,无论用户访问什么路径,Vercel 都会返回
index.html
,让前端路由接管。
- 操作步骤:
- 在项目的
public
目录下创建一个名为vercel.json
的文件(确保打包后vercel.json
文件会在根目录的位置)。 - 将上述内容复制到文件中。
- 部署项目到 Vercel。
- 在项目的
当然我们的博客项目并不需要使用history路由,因为我们的博客项目是多页面应用程序
根据项目部署的位置不同,上述json文件可能也需要做适当的修改,不过无论如何, vercel.json
都应该放到服务器的根目录下,下面分享一下我部署项目编写的json文件:
1 | { |
优化加载速度
1 | //_config.butterfly.yml |
我们可以通过下载hexo-butterfly-extjs
:
1 | npm i hexo-butterfly-extjs |
并配置third_party_provider
为local
,然后我们加载一些第三方的css
和js
文件就不需要通过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 | const fs = require('fs'); |
然后这个文件就会被打包到public目录的根目录下。
然后我们还要修改一下部署指令,每次部署的时候,自动删除这个文件
1 | "scripts": { |
其他加速vercel的方法参考:Vercel 加速,快,不止更快 | Mystic Stars,总结一下这篇文章的加速方法:
将原来解析至
cname.vercel.com
改为vercel.cdn.yt-blog.top
。vercel.cdn.yt-blog.top
类似一个加速域名,会返回一个响应当前请求最合适的ip地址,Vercel 在大陆周围还有很多节点,其中包含中国台湾、韩国、日本、新加坡等,这些节点的访问延迟在接受范围,且相对香港节点来说带宽更充足,而 解析cname.vercel.com
只会返回美国服务器的ip。通过Vercel官方提供的缓存进行加速。在服务器根目录放置
vercel.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{
"headers": [
{
"source": "/sw.js",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=0, must-revalidate"
}
]
},
{
"source": "(.*)",
"headers": [
{
"key": "Cache-Control",
"value": "public, s-maxage=86400, max-age=86400"
}, {
"key": "Vercel-CDN-Cache-Control",
"value": "max-age=86400"
}
]
}
]
}Vercel在部署时会自动刷新缓存,静态网站缓存可以拉到无限长,动态网站缓存按实际需要,即便你担心缓存导致无法获取最新的资源,也可以通过打开开发者工具,清空缓存并硬刷新来清除当前页面的缓存。
购买云服务器
vercel的优缺点
使用vercel部署博客优点很多,比如:
- 项目提交到
github
后自动部署到vercel
,省心省力 - 提供免费的ssl证书,支持https协议访问,而且自动为ssl证书续期。
- 在国内访问速度良好
- 完全免费,不需要担心流量费用
但也有缺点:
- 不能上传大小超过100mb的文件
- 在国内不存在CDN服务器,无论如何优化加载速度,在晚上的访问速度还是不尽如人意。
最终的解决方案,应该就是购买国内的服务器了吧,不过把自己的博客部署好也还要花时间
在服务器上搭建博客
购买云服务可以考虑去阿里云或者腾讯云等网站,搜索”学生优惠”,通常能以非常便宜的价格购买到云服务器。
传输自己的博客静态文件到服务器:如何将本地文件拷贝到云服务器,其实阿里云本身也提供了
远程连接到服务器
的功能,但是并不能传输本地文件到服务器。下载
nginx
,修改配置文件,使用nginx
部署自己的博客即可。nginx的基本操作(windows系统):修改配置文件
nginx.conf
,只需要修改小部分即可,非常简单,可自行百度。双击
nginx.exe
文件,看到命令行窗口一闪而过,表示服务器启动成功,或者cd到对应目录,在命令行输入nginx
并执行。运行
nginx -t
,检查配置文件格式是否正确。在修改配置文件后运行
nginx -s reload
,重启服务器。
服务器启动后,如果同时配置了http和https,则默认会占用80和443端口,在浏览器上使用公网ip发送请求,服务器就能成功接收并处理请求并返回相关数据。
同时,我们还要在自己的云服务器实例的
安全组
那里,开启80和443端口,否则我们还是无法通过http和https协议访问我们的云服务器。如果需要支持
https
,还要申请ssl证书,然后安装到服务器(还需在nginx配置证书的访问路径),可以去腾讯云申请免费的ssl证书:我的证书 - SSL 证书 ,申请证书要验证域名(验证域名是不是你的),我们申请的ssl证书是要和自己的域名绑定的,如果我们在服务器安装了证书,之后不是使用绑定的域名来访问我们的服务器(比如直接通过ip地址访问),浏览器就会提示:”当前连接不安全“,”你的连接不是专用连接“。如果证书已经过期,同样弹出上述安全提示。我们购买的云服务器会提供一个公网ip地址,我们可以直接使用这个ip,访问到我们的服务器,不需要备案。
但是我们如果想要添加域名,就必须对域名进行备案,备案貌似只能通过阿里云等互联网服务提供商,全网最详细:个人网站如何备案 - 知乎,不过我测试了一下,即便没备案,在域名控制台添加对应的A记录后,也能通过域名访问到自己的服务器,但是这种情况应该不会持续太久,因为是违法的。
要注意的是,在阿里云上,以
按量付费
方式购买的云服务器,不支持进行域名备案。
优缺点
- 云服务需要购买,虽然参加某些活动,或者以学生的身份购买服务器,能以非常便宜的价格买到云服务器
- 流量费用需要自行支付
- 需要自行传输博客文件到服务器,比较麻烦
- 需要自行申请ssl证书并安装,否则无法通过https协议访问,证书过期后肯能还需要手动续期
- 绑定域名需要备案,备案的过程较为麻烦
- 服务器在国内,在国内的访问速度可观。
- 因为有自己的服务器,所以也可以自己编写后端接口,给自己的博客添加一些动态的功能。
一些思考
云服务器的云盘与个人电脑硬盘的相似之处
存储数据:就像你的个人电脑硬盘用来存储操作系统、软件和个人文件一样,云盘用于存储云服务器的操作系统、应用程序以及你上传或生成的数据。
容量选择:你可以根据需求选择不同大小的云盘,类似于在购买新电脑时选择不同容量的硬盘
我们购买电脑的时候不会说给一个公网ip,但是购买云服务器就会送公网ip
这是因为个人电脑通常连接的是家庭或办公室的私有网络,通过路由器等设备接入互联网,使用的是局域网(LAN)内的私有IP地址,路由器会通过网络地址转换(NAT)技术,共享一个公网IP地址给内部的所有设备。
云服务器是部署在互联网服务提供商的数据中心内,直接连接到互联网上。为了使这些服务器能够被外界访问,通常会提供一个公网IP地址。这个公网IP地址允许用户从任何地方,通过互联网直接访问你的云服务器,这对于运行网站、应用程序,或其他需要外部访问的服务来说至关重要。总之,云服务器配备公网IP是为了便于其提供的服务可以直接被外界访问,而这也是区别于个人电脑的一个重要特征。
感想与结语
hexo+butterfly框架
能帮助我们迅速开发一个美观实用的博客,这些框架,主题,以及相关插件的诞生,基于开发者雄厚的html,css,js等前端知识积累;做为刚入们的前端开发者,我也知道给光看文档能学到的实在是有限,在网上找资料学到的也是偏向实践,想要深入了解原理,自己做出这些效果,还得多学多练,打好自己前端基础。
如果你还想进一步美化自己的博客,给自己的博客添加更多的功能,你可以选择不断的阅读butterfly官方文档,也可以去网上查找更多的资料,以下是我推荐的一些资料,希望能帮助到你。
- Hexo官方文档
- butterfly魔改教程:页面 | Butterfly主题美化教程
- md语法学习
- butterfly主题官方文档:Butterfly - A Simple and Card UI Design theme for Hexo
- NameSilo官网
- 鼠标指针 - 光标 - 电脑鼠标指针下载 - 致美化 - 漫锋网
- demo