前言
本博客的搭建参考了众多博主的搭建教程(文章主体结构参考Hexo+Github博客搭建完全教程最多),因为时间有限且个人属于前端小白,故个性化做得不是很好,还有许多需要完善的地方。另外搭建个人博客需要一些耐心,很多细节都会导致Bug的出现。本文的内容随意复制,引用的话可以加一个参考链接,谢谢😁 。希望大家都能搭建好自己舒适的博客~
搭建原因及思路
原因
- 之前是在博客园上写文章,但是总是感觉不舒服,因为有些广告啥的,另外虽然想做一些个性化,但一是因为自己是个前端小白,好多东西不会;二是不太愿意花那么多时间去弄一个不属于自己的东西。没错,第三方的平台会给我一种疏离感,而个人博客个性化极强,从头到尾这么搭建下来,不得不说心理极度舒适😂。除此之外,大一的时候上导论课也接触过一些关于服务器、前端、网站等等,也算是种下了一颗种子,但奈何自己太菜又太懒,一直没有下定决心去做。现在趁着大三暑假,花点时间搭建个人博客,也算是解决了一个心结。
思路
基于开源框架
Hexo搭建博客,直接在GitHub Pages平台上托管博客其实也可以在
Coding或Gitee上部署,Coding我没有尝试,但Gitee由于最近在创建绿色网络环境,Pages暂停服务了,现在没法申请。因为打算白嫖,所以没有买个人域名,如果买了个人域名,在
GitHub上绑定之后即可访问。我白嫖的地址:https://321hjd.github.io/
教程结构安排
- 第一部分:
Hexo的初步搭建以及部署至GitHub Pages上 - 第二部分:
Hexo的主题更换以及基本配置 - 第三部分:个性化。添加各种功能,如评论系统、说说模块等
- 第四部分:博客的性能优化
一、搭建
Hexo的初步搭建以及部署至GitHub Pages上
工具说明
-
是一个基于
Node.js的快速, 简洁且高效的静态网站生成框架. 让上百个页面在几秒内瞬间完成渲染.Hexo支持Github Flavored Markdown的所有功能, 甚至可以整合Octopress的大多数插件. 并自己也拥有强大的插件系统. -
Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。Git是Linus Torvalds为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。Git与常用的版本控制工具CVS, Subversion等不同,它采用了分布式版本库的方式,不必服务器端软件支持。 -
简单的说
Node.js就是运行在服务端的JavaScript。Node.js是一个基于Chrome JavaScript运行时建立的一个平台。Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行JavaScript的速度非常快,性能非常好。 -
是
JavaScript世界的包管理工具,并且是Node.js平台的默认包管理工具
1. 安装Git
- Windows:到Git官网下载
.exe文件,安装选项全默认- 安装完成后使用右键的
Git Bash Here,执行git --version可查看版本号
- 安装完成后使用右键的
- Linux:只需要一行指令
sudo apt install git即可 - Git教程:廖雪峰老师写的Git教程非常好,强烈建议大家看看
2. 安装Node.js和npm工具
- Windows:到Node.js官网下载,安装选项全默认
- 安装好之后,按
win+R打开cmd,输入node -v和npm -v,若出现版本号,说明成功
- 安装好之后,按
- Linux:
- 安装及配置环境变量:参考Hexo+Github博客搭建完全教程
3. 安装Hexo
找个地方右键
Git Bash Here,后面的指令操作都是使用Git Bash配置
npm的国内镜像源:npm install -g cnpm --registry=https://registry.npm.taobao.or配置完成后,输入
npm info hexo,如果配置成功,dist会显示.tarball: https://registry.nlark.com/hexo/download/hexo-5.4.0.tgz通过
npm安装Hexo(-g是指定全局安装,之后可以在任意位置使用hexo指令)npm install -g hexo然后输入
hexo -v查看是否安装成功。若出现版本号,则至此已安装完成接下来初始化我们的静态网站,进入到存放博客文件的目录下
hexo init MyBlog # 初始化创建,将在当前目录下新建MyBlog文件夹 cd MyBlog # 进入这个文件夹,这个文件夹下面将存放所有相关文件 npm install # 进一步安装hexo所需文件大概效果如下:

指令执行完成后,指定文件夹
MyBlog目录下有:node_modules/:Hexo的依赖包scaffolds/:生成文章的一些模板source/:用来存放写的文章themes/:主题_config.yml:博客的配置文件- 其它:
.github/、.gitignore、_config.landscape.yml、package.json、package-lock.json
打开本地服务器查看博客
hexo generate # 生成静态网页 hexo server # 打开本地服务器(默认是4000端口)正常情况下应该会出现下图:

这时博客根目录下会生成
public目录,这就是我们部署到GitHub上所需要上传的文件夹。Ctrl + C可关闭本地服务器
4. 注册GitHub账号并新建个人仓库
GitHub:https://github.com/新建项目仓库
new repository,注意项目名字最好是和用户名相同,并加上.github.io后缀。比如我的repo:321hjd.github.io注意勾选上
README初始化,可以描述一下该repo是干嘛的然后在项目页面选择
Setting并下拉,进入Pages,可以看到分配给自己的Pages(如果没正常显示,可能还差点啥,具体记不太清楚了,当时没记录😢)
5. 生成本地SSH并添加至GitHub
生成
SSH并添加至GitHub,使得GitHub可以识别本地(name和email可以和注册Github时的不同)git config --global user.name "yourname" # name按自己喜好取 git config --global user.email "youremail" # global代表本机上任一地方的Git用户都是此处设置的创建
SSHssh,简单来讲,就是一个秘钥,其中,id_rsa是你这台电脑的私人秘钥,不能给别人看的,id_rsa.pub是公共秘钥,可以随便给别人看。把这个公钥放在GitHub上,这样当你链接GitHub自己的账户时,它就会根据公钥匹配你的私钥,当能够相互匹配时,才能够顺利的通过git上传你的文件到GitHub上。ssh-keygen -t rsa -C "youremail" # 刚刚设置的email这时它会告诉你已经生成了
.ssh文件夹,应该是在系统盘的用户目录下,如:C:\Users\username\.ssh。找到该文件夹并复制id_rsa.pub中的所有内容打开
GitHub,在头像下面点击Settings,再点击SSH and GPG keys,新建一个SSH,随便取一个名字,然后将刚刚复制的内容全部粘贴进去,如图:
再在
git bash输入ssh -T git@github.com,若出现如下结果,则添加成功
至此,我们已经可以在本地建立
repo并与GitHub连接起来,如pull or push
6. 将Hexo部署至GitHub
这一步,会将
Hexo生成的文章部署到GitHub上。首先我们需要安装一个插件
deployer-git,这样我们才能用命令部署至GitHubnpm install hexo-deployer-git --save然后打开博客根目录的
_config.yml文件,修改
url部分并新增root,写为url: https://{username}.github.io/ # Pages地址 root: / # 网站根目录修改最后一行的配置
deploy: type: git repository: https://github.com/{username}/{yourrepo} # 示例:https://github.com/321hjd/321hjd.github.io branch: master
最后执行以下命令,部署成功,此时可以访问
GitHub分配的Pages如我的https://321hjd.github.io看到博客主页hexo clean # 清除缓存(网页正常情况下可以忽略此条命令,执行该指令后,会删掉站点根目录下的public文件夹) hexo generate # 生成静态页面至public目录 hexo deploy # 自动生成网站静态文件并部署到设定仓库注意:若这一步完成后访问不了
Pages,可以参考本节的Q&A,若还是无法解决,请仔细查看上述步骤是否正常完成,或根据本节的参考链接跳转至其他大佬处查询。
7. 写文章并发布文章
建议写一个test文档,专门用于测试功能是否能正确实现。
另外markdown编辑器建议使用Typora,非常好用~
新建test文档。在博客根目录下右键打开
git bash,执行指令hexo new post "test"- 此时打开
xxx/source/_posts可以发现多了一个test.md - 编辑该文件并执行
hexo g、hexo s可以本地预览,也可以继续执行hexo d部署至GitHub,这时候就可以在你的Pages上看到发布的文章了
- 此时打开
Q&A
Q:使用GitHub的pages服务,部署到
GitHub后访问username.github.io总是无法连接(手机热点/WiFi都不行,不知道为啥)
A:在站长之家查看博客(https://{username}.github.io)的IP地址,修改C:\Windows\System32\drivers\etc\HOSTS文件(需要管理员权限),将IP地址 {username}.github.io添加到文件最后即可(如185.199.111.153 321hjd.github.io)。(枯了,还是有缺陷,电脑连手机热点的时候没法访问,只能用WiFi,但是手机热点上GItHub感觉又要容易一些😢,Gitee的Pages服务快点恢复吧😭)
参考链接
二、主题基本配置
1. Hexo相关目录文件介绍
具体都可以参考官方文档
1.1 博客目录结构
- node_modules # node.js库目录
- public # 生成的网页文件目录
- scaffolds # 新文章或页面的模板文件
- source # 最常用的目录,后面个性化会新增很多
- _data # 存放一些页面的配置文件
- _posts # 文章存放的目录
- about # “关于”页面
- archives # “归档”页面
- categories # “分类”页面
- friends # “友情链接”页面
- tags # “标签”页面
- themes # 存放主题
1.2 Hexo基本配置
网站信息
title: Hexo # 网站标题 subtitle: '' # 网站副标题 description: '' # 网站描述,主要用于SEO,告诉搜索引擎一个关于您站点的简单描述,通常建议在其中包含您网站的关键词 keywords: # 网站关键词 author: John Doe # 作者 language: en # 语言,简体中文比如zh-CN(可以后面换了主题后再改) timezone: '' # 时区,比如UTC/America/Japan,可以不填网址
url: # 网址 root: # 网站根目录 permalink: :year/:month/:day/:title/ # 文章的永久链接格式 permalink_defaults: # 永久链接中各部分的默认值 ...使用默认的
permalink的话,生成文章test.md的链接就是https://{username}.github.io/2021/7/22/test后面会将关于
permalink的优化(主要是防止修改文章名后链接发生变化)
主题:
theme: landscap,默认是landscape,要更换主题下载后放入themes文件夹下,然后修改此处即可Front-matterFront-matter是md文件最上方以---分隔的区域,用于指定个别文件的变量,具体可参考Front-matter注意下面部分属性是需要下载主题以后才能配置的,暂时默认就好,后续更换主题后再改也不迟~
title: "test" # 文章标题,可以和.md文件名不同(注意Windows下文件名特殊字符的问题) date: 2021-07-21 14:46:34 # 文章生成日期 author: hjd # 作者 img: # 文章封面图片,缺省应该是会按照一定的规则从主题目录下的xxx/source/medias/featureimages/中拉取图片 coverImg: # 轮播图片 top: false # 置顶 cover: false # 是否在首页进行轮播 toc: true # 目录 mathjax: false # 是否支持mathjax,即数学公式 password: # 文章密码 summary: # 简介 tags: # 标签,注意多级标签这样写 - tag1 - tag2 - ... categories: # 分类layout三种默认布局:
post、page、draft,即scaffolds目录下的三个模板- 注意:那三个模板中的
Front-matter是可以修改的
- 注意:那三个模板中的
post:当使用指令hexo new test时,默认使用的布局是post,即source/_posts/下的文件,完整指令应该是hexo new {layout} "title"page:执行hexo new page newpage,会在source目录下新建newpage文件夹和其中的index.md,这样访问该newpage的路径就是:https://{username}.github.io/newpagedraft:草稿,想写文章但不想别人看或者暂时不发出去,即预览或部署时令系统忽略该文章- 执行
hexo new draft newdraft,会生成source/_drafts/newdraft.md文件 - 想要预览该草稿时,可以执行
hexo server --draft指令 - 想要将草稿发表致至
_posts中,执行hexo publish draft newdraft即可(_draft/中的test.md将被移动至_posts/)
- 执行
2. 更换主题
注意,我使用的主题是hexo-theme-matery(
README中有配置相关介绍)。当然你也可以使用其它主题比如相当受欢迎的NexT。后续教程全部都是针对matery主题的,部分地方可以相互借鉴,但存在一定差异,请各位看官斟酌。关于该主题的特性就不多说了,
GitHub上有介绍,大家git clone下来后也可以自行体会,下面主要介绍基本的一些配置和问题的解决。关于下面的一些功能实现,建议大家专门写一个
test.md来测试每一项功能。
2.1 下载主题并更换
在
themes/目录下执行该指令git clone https://github.com/blinkfox/hexo-theme-matery.git然后将博客根目录下
_config.yml中的theme属性值改为hexo-theme-matery
2.2 添加404页面
在
/source/目录下新建404.mdtitle: 404 date: 2021-07-14 00:00:00 type: "404" layout: "404" description: "经典404 Not Found →_→"然后在
/themes/hexo-theme-matery/layout目录下新建一个404.ejs文件<style type="text/css"> /* don't remove. */ .about-cover { height: 90.2vh; } </style> <div class="bg-cover pd-header about-cover"> <div class="container"> <div class="row"> <div class="col s10 offset-s1 m8 offset-m2 l8 offset-l2"> <div class="brand"> <div class="title center-align"> 404 </div> <div class="description center-align"> <%= page.description %> </div> </div> </div> </div> </div> </div> <% if (theme.banner.enable) { %> <script> // 每天切换 banner 图. Switch banner image every day. var bannerUrl = "<%- theme.jsDelivr.url %><%- url_for('/medias/banner/') %>" + new Date().getDay() + '.jpg'; $('.bg-cover').css('background-image', 'url(' + bannerUrl + ')'); </script> <% } else { %> <script> $('.bg-cover').css('background-image', 'url(<%- theme.jsDelivr.url %><%- url_for('/medias/banner/0.jpg') %>)'); </script> <% } %>
2.3 代码高亮
根据hexo-theme-matery的配置建议,直接使用
prismjsnpm uninstall hexo-prism-plugin # 若node_modules中有hexo-prism-plugin插件,先写在然后修改博客根目录下的
_config.yml配置文件highlight: enable: false # 改为false line_number: true auto_detect: false tab_replace: '' wrap: true hljs: false prismjs: enable: true # 改为true preprocess: true line_number: true tab_replace: ''默认的
prismjs主题是Tomorrow Night,若需要更换,到prismjs download page下载喜欢的css文件,然后替换themes/hexo-theme-matery/source/libs/prism/prism.css即可这里发现了一些问题,如c++、yml等无法高亮,暂时还没找到解决方案⊙﹏⊙∥。
另外注意代码块前面不能有列表符号,否则不能正常渲染。
2.4 数学公式渲染
存在的问题:
Hexo默认的渲染引擎hexo-renderer-marked和markdown语法冲突,因为该引擎会将一些特殊的markdown符号转换为相应的HTML标签,比如在markdown语法中,下划线'_'代表斜体,但会被该渲染引擎处理为<em>标签,类似的还有'*'、'{'、'}、'\'等解决方案:
更换
Hexo的渲染引擎npm uninstall hexo-renderer-marked --save # 卸载原来的引擎 npm install hexo-renderer-kramed --save # kramed是与marked相近的轻量级渲染引擎,只是在后者的基础上修复了一些bug然后修复一些行内渲染的
bug。- 打开博客根目录的
node_modules/kramed/lib/rules/inline.js文件,将第11行的escape变量做相应修改(这一步是在原基础上取消了对\,{,}的转义)
// escape: /^\\([\\`*{}\[\]()#$+\-.!_>])/, escape: /^\\([`*\[\]()#$+\-.!_>])/, //注意需要逗号- 同时将第20行的
em变量做相应修改
// em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, em: /^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,- 打开博客根目录的
接下来在主题中开启
mathjax开关。打开主题目录下的配置文件_config.yml,将mathjax默认的false修改为truemathjax: enable: true per_page: true cdn: https://cdn.bootcss.com/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML最后在文章的
Front-matter中开启mathjax(不需要数学公式的文章建议关闭,因为mathjax的渲染较为耗时)--- title: test author: hjd mathjax: true tags: ---
最后还是存在一点问题,比如连续的花括号渲染时会失败。不过在中间加上空格就好了。ps:这是参考教程说的,但可能后面作者已经修复了这个bug,我测试的时候并没有发现有问题😂
2.5 文章图片引用
问题:部署后文章中插入的图片不显示
解决方案
- 首先安装插件
hexo-asset-image:
npm install https://github.com/7ym0n/hexo-asset-image --save然后打开博客根目录的
_config.yml,将post_asset_folder的值修改为true(这时再生成文章时会在_posts目录下生成与文章同名的文件夹)其实这一步也可以不用,看个人喜好,是不是喜欢把同一篇文章的图片都放在一起
最后插入图片的路径有三种
- 方法一:
(缺点是本地Typora无法预览) - 方法二:相对路径。
(这种方法建议打开上一步那个post_asset_folder开关;或者直接建一个文件夹专门存放所有文章的图片) - 方法三:
{% asset_img example.jpg This is an example image %}(参考自官方文档)
- 方法一:
当然还有一种方法是直接将图片上传到图床,然后直接引用图床链接。
- 首先安装插件
2.6 添加表情支持
目的:令博客可以使用
markdown的表情语法(如<span class="github-emoji" alias="cry" style="" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f622.png?v8">😢</span>是😢)最开始是根据网上很多的教程包括
matery的官方README文件的描述,安装hexo-filter-github-emojis,但奈何安装时总是报错,最后使用了next-theme主题的emoji插件:hexo-filer-emoji# npm install hexo-filter-github-emojis --save # 大家可以先试试这个 npm install hexo-filter-emoji --save然后配置博客根目录配置文件
_config.yml的emoji属性即可# 添加GitHub的emoji支持 emoji: enable: true className: github-emoji styles: customEmojis:
2.7 添加建站时间
修改
/themes/hexo-theme-matery/layout/_partial中的footer.ejs,在最后加上:(原来的文件中似乎有这部分代码,看情况修改吧)<script language=javascript> function siteTime() { window.setTimeout("siteTime()", 1000); var seconds = 1000; var minutes = seconds * 60; var hours = minutes * 60; var days = hours * 24; var years = days * 365; 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(); /* Date.UTC() -- 返回date对象距世界标准时间(UTC)1970年1月1日午夜之间的毫秒数(时间戳) year - 作为date对象的年份,为4位年份值 month - 0-11之间的整数,做为date对象的月份 day - 1-31之间的整数,做为date对象的天数 hours - 0(午夜24点)-23之间的整数,做为date对象的小时数 minutes - 0-59之间的整数,做为date对象的分钟数 seconds - 0-59之间的整数,做为date对象的秒数 microseconds - 0-999之间的整数,做为date对象的毫秒数 */ var t1 = Date.UTC(2017, 09, 11, 00, 00, 00); //北京时间2018-2-13 00:00:00 var t2 = Date.UTC(todayYear, todayMonth, todayDate, todayHour, todayMinute, todaySecond); var diff = t2 - t1; 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("sitetime").innerHTML = "本站已运行 " +diffYears+" 年 "+diffDays + " 天 " + diffHours + " 小时 " + diffMinutes + " 分钟 " + diffSeconds + " 秒"; }/*因为建站时间还没有一年,就将之注释掉了。需要的可以取消*/ siteTime(); </script>然后在前面如
copyright声明后加上以下代码即可<br> <span id="sitetime"></span><span class="my-face">(ง •_•)ง</span> <br>
2.8 不蒜子初始化计数
修改
/themes/hexo-theme-matery/layout/_partial中的footer.ejs,在最后加上:<script> $(document).ready(function () { var int = setInterval(fixCount, 50); // 50ms周期检测函数 var pvcountOffset = 0; // 初始化首次数据 var uvcountOffset = 0; function fixCount() { if (document.getElementById("busuanzi_container_site_pv").style.display != "none") { $("#busuanzi_value_site_pv").html(parseInt($("#busuanzi_value_site_pv").html()) + pvcountOffset); clearInterval(int); } if ($("#busuanzi_container_site_pv").css("display") != "none") { $("#busuanzi_value_site_uv").html(parseInt($("#busuanzi_value_site_uv").html()) + uvcountOffset); // 加上初始数据 clearInterval(int); // 停止检测 } } }); </script>然后把上面关于不蒜子的一段代码增加两个
style='display:none'<% if (theme.busuanziStatistics && theme.busuanziStatistics.enable) { %> <% if (theme.busuanziStatistics && theme.busuanziStatistics.totalTraffic) { %> <span id="busuanzi_container_site_pv" style='display:none'></span> | <i class="far fa-eye"></i> <%- __('siteTotalVisits') %>: <span id="busuanzi_value_site_pv" class="white-color"></span> <% } %> <% if (theme.busuanziStatistics && theme.busuanziStatistics.totalNumberOfvisitors) { %> <span id="busuanzi_container_site_uv" style='display:none'></span> | <i class="fas fa-users"></i> <%- __('siteTotalVisitors') %>: <span id="busuanzi_value_site_uv" class="white-color"></span> <% } %> <% } %>
注意这里除了增加了两个
style='display:none',还修改了两个<span>的位置,顺带也解决了后面不蒜子计数与live2d模型的冲突。如果要看每一步的操作,请移步洪卫大佬的教程:Hexo+Github博客搭建完全教程
2.9 字数统计、访问人数及其它
添加文章总字数、站点访问人数、站点文章总字数以及文章更新日期
- 下载
hexo-wordcount插件
npm i --save hexo-wordcount- 修改主题配置文件
_config.yml,激活配置即可
postInfo: date: true # 发布日期 update: true # 更新日期 wordCount: true # 文章字数统计 totalCount: true # 站点总文章字数 min2read: true # 文章阅读时长 readCount: false # 文章阅读次数- 注意此时还不能看到站点文章总字数的统计,还需修改
/themes/hexo-theme-matery/layout/_partial中的footer.ejs,添加如下代码
<% if (theme.postInfo.totalCount) { %> <i class="fas fa-chart-area"></i> 站点总字数: <span class="white-color"><%= totalcount(site) %></span> 字 <% } %>- 下载
开启首页轮播功能
- 配置
source/_data/cover.json或直接将文章Front-Matter中的cover属性置为true即可
- 配置
添加搜索功能
下载
hexo-generator-search插件:npm install hexo-generator-search --save然后在根目录下的
_config.yml中配置search: path: search.xml field: post
修改
scaffolds下模板的Font-matter,放出我的:post和draft建议用一样的title: {{ title }} date: {{ date }} author: hjd img: coverImg: top: false cover: false toc: true mathjax: false password: summary: tags: categories:pagetitle: {{ title }} date: {{ date }} type: layout:
其它:如友情链接、关于等页面可参考hexo-theme-matery官方文档
参考链接
- Hexo+Github博客搭建完全教程
- 在Hexo中渲染MathJax公式
- hexo-theme-matery官方文档
- Luckysec博客源码:xx/matery/layout/_partial/footer.ejs
三、个性化
1. 添加博客动态标签
打开
themes/hexo-theme-matery/layout/layout.ejs,在对应位置添加如下代码即可<script type="text/javascript"> var OriginTitile = document.title, st; document.addEventListener("visibilitychange", function () { document.hidden ? (document.title = "🙈😜有本事点我", clearTimeout(st)) : (document.title = "( ఠൠఠ )ノ啊你还真点啊", st = setTimeout(function () { document.title = OriginTitile }, 3e3)) }) </script>
2. 修改壁纸、添加live2d模型
修改壁纸:在
themes\Matery\source\css\matery.css文件中找到body,修改如下body { /*background-color: #eaeaea;*/ background: linear-gradient(60deg, rgba(255, 165, 150, 0.5) 5%, rgba(0, 228, 255, 0.35)) 0% 0% / cover, url("https://ae01.alicdn.com/kf/H18a4b998752a4ae68b8e85d432a5aef0l.png"), url("https://i.loli.net/2021/07/17/kYX7dl5qtKpVeMv.jpg") 0px 0px; background-attachment: fiexd; margin: 0; color: #34495e; overflow-x: hidden; overflow-y: auto; }添加
live2d模型安装依赖:
npm install --save hexo-helper-live2d安装模型(可以上网搜搜有哪些模型,这里以狗狗为例),先在博客根目录的
_config.yml中新增配置# live2D模型配置 live2d: enable: true scriptFrom: local pluginRootPath: live2dw/ pluginJsPath: lib/ pluginModelPath: assets/ tagMode: false debug: false model: use: live2d-widget-model-wanko display: position: right hOffset: 100 # 水平偏移 vOffset: -50 # 垂直偏移 width: 150 height: 300 mobile: # 手机显示开关 show: true react: opacity: 0.7然后执行指令即可:
npm install live2d-widget-model-wanko
注意:这里模型与不蒜子似乎有冲突,不过前面添加建站时间部分已经顺带解决了。即修改
<span>的部分。
3. 取消渐变色、滚动条美化、直达评论按钮
取消渐变色:在
themes\Matery\source\css\matery.css找到.bg-cover:after,注释掉即可/*去除首页蒙版*/ /*.bg-cover:after { -webkit-animation: rainbow 60s infinite; animation: rainbow 60s infinite; }*/滚动条美化:在
themes\Matery\source\css\matery.css样式添加如下:/* 滚动条 */ ::-webkit-scrollbar-thumb { background-color: #00FFFF; background-image: -webkit-linear-gradient(45deg,rgba(255,255,255,.4) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.4) 50%,rgba(255,255,255,.4) 75%,transparent 75%,transparent); border-radius: 3em; } ::-webkit-scrollbar-track { background-color: #CCFFCC; border-radius: 3em; } ::-webkit-scrollbar { width: 8px; height: 15px; }直达评论按钮(这一条可以等添加完
Valine评论模块再做)新建文件
themes\Matery\layout\_partial\back-comment.ejs,粘贴如下代码(我这里评论是valine,直接填写的valine的id——href="#vcomments",如果是其他评论,对应修改即可。)<!-- 直达评论 --> <div id="to_comment" class="comment-scroll"> <a class="btn-floating btn-large waves-effect waves-light" href="#vcomments" title="直达评论"> <i class="fas fa-comments"></i> </a> </div>在
themes\Matery\layout\_partial\valine.ejs文末添加一条,引用第一步的内容<%- partial('_partial/back-comment.ejs') %>增加样式。在
themes\Matery\source\css\matery.css添加内容如下:/*直达评论按钮样式*/ .comment-scroll { position: fixed; right: 15px; bottom: 135px; padding-top: 15px; margin-bottom: 0; z-index: 998; } .comment-scroll .btn-floating { background: linear-gradient(to bottom right, #FF9999 0%, #00FFFF 100%); width: 48px; height: 48px; } .comment-scroll .btn-floating i { line-height: 48px; font-size: 1.8rem; }
4. 导航栏优化
4.1 菜单修改
这里修改了一些菜单的布局,主要是做了如下改变:
- 将时轴、标签、分类放入归档页面下
- 新增一级菜单-清单,并在其下添加相册、音乐、书单、电影、资源等页面
- 新增一级菜单-说说、工具箱
方法:
修改主题下的
_config.yml(参考注释即可),如:menu: Index: url: / icon: fas fa-home Archives: icon: fas fa-archive children: - name: 时轴 url: /archives icon: fas fa-paper-plane - name: 分类 url: /categories icon: fas fa-bookmark - name: 标签 url: /tags icon: fas fa-tags List: icon: fas fa-heartbeat children: - name: 音乐 url: /music icon: fas fa-music - name: 相册 url: /galleries icon: fas fa-image - name: 书单 url: /books icon: fas fa-list - name: 电影 url: /films icon: fas fa-film - name: 资源 url: /resources icon: fas fa-cloud-download-alt About: url: /about icon: fas fa-user-circle Artitalk: url: /artitalk icon: fas fa-heart Contact: url: /contact icon: fas fa-comments Friends: url: /friends icon: fas fa-address-book Tools: url: /tools icon: fas fa-toolbox- 其中的
icon图标可以到Font Awesome中选择自己喜欢的
- 其中的
然后需要新建对应的
page(方法同建立关于、友链等页面)hexo new page music hexo new page galleries hexo new page books hexo new page films hexo new page resources hexo new page artitalk hexo new page tools- 记得将对应生成的
index.md中的type和layout都改为对应的标题
- 记得将对应生成的
汉化。需要修改两个文件:
themes/hexo-theme-matery/layout/_partial/下的navigation.ejs和mobile-nav.ejs,模仿源代码添加几行代码即可var menuMap = new Map(); menuMap.set("Index", "首页"); menuMap.set("Tags", "标签"); menuMap.set("Categories", "分类"); menuMap.set("Archives", "归档"); menuMap.set("About", "关于"); menuMap.set("Artitalk", "说说"); menuMap.set("Contact", "留言板"); menuMap.set("Friends", "友情链接"); menuMap.set("List", "清单"); menuMap.set("Tools", "工具箱");
4.2 相册
上一步已经新建了
galleries页面,其type和layout均为galleries添加
themes/hexo-theme-matery/source/css/gallery.css文件.gallery-wrapper{ padding-top: 30px; } .gallery-wrapper .gallery-box{ padding: 5px !important; } .gallery-wrapper .gallery-item { display: block; overflow: hidden; background-color: #fff; padding: 5px; padding-bottom: 0; position: relative; -moz-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.22); -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.22); box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.22); } .gallery-cover-box{ width: 100%; padding-top: 60%; text-align: center; overflow: hidden; position: relative; background: center center no-repeat; -webkit-background-size: cover; background-size: cover; } .gallery-cover-box .gallery-cover-img { display: inline-block; width: 100%; position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); } .gallery-item .gallery-name{ font-size: 14px; line-height: 24px; text-align: center; color: #666; margin: 0; } .waterfall { column-count: 3; column-gap: 1em; } .photo-wrapper{ padding-top: 20px; } .photo-item { display: block; padding: 10px; padding-bottom: 0; margin-bottom: 14px; font-size: 0; -moz-page-break-inside: avoid; -webkit-column-break-inside: avoid; break-inside: avoid; background: white; -moz-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.22); -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.22); box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.22); } .photo-item img { width: 100%; } .photo-item .photo-name{ font-size: 14px; line-height: 30px; text-align: center; margin-top: 10px; margin-bottom: 10px; border-top: 1px solid #dddddd; } /*适配移动端布局*/ @media only screen and (max-width: 601px) { .waterfall { column-count: 2; column-gap: 1em; } }在
themes/hexo-theme-matery/layout/目录下新建galleries.ejs和gallery.ejs文件注意:此处
galleries.ejs是整个相册页面的配置,gallery.ejs是单独某一个相册的配置。- 这是
galleries.ejs文件
注意其中
https://cdn.jsdelivr.net/gh/321hjd/ImageBed/galleries/是我使用CDN加速后的图床链接(后面会讲到图床搭建和CDN加速,可以先使用我的看看效果,这也是需要修改的地方,具体如何取决于你的/source/_data/galleries.json如何配置)<link rel="stylesheet" href="/css/gallery.css"> <%- partial('_partial/bg-cover') %> <main class="content"> <div class="container"> <% if (site.data && site.data.galleries) { %> <% var galleries = site.data.galleries; %> <div class="gallery-wrapper row"> <% for (var i = 0, len = galleries.length; i < len; i++) { %> <% var gallery = galleries[i]; %> <div class="col s6 m4 l4 xl3 gallery-box"> <a href="./<%- gallery.name %>" class="gallery-item" data-aos="zoom-in-up"> <div class="gallery-cover-box" style="background-image: url(https://cdn.jsdelivr.net/gh/321hjd/ImageBed/galleries/<%- gallery.cover%>)"> <!--<img src="https://cdn.jsdelivr.net/gh/321hjd/ImageBed/galleries/<%- gallery.cover %>" alt="img" class="gallery-cover-img">--> </div> <p class="gallery-name"> <%- gallery.name %> </p> </a> </div> <% } %> </div> <% } %> </div> </main>- 这是
gallery.ejs文件,同样url需要修改为自己的图床地址
<link rel="stylesheet" href="/css/gallery.css"> <link rel="stylesheet" type="text/css" href="<%- theme.libs.css.fancybox %>"> <link rel="stylesheet" type="text/css" href="<%- theme.libs.css.justifiedGallery %>"> <%- partial('_partial/post-cover') %> <% let galleries = []; if (site.data && site.data.galleries) { galleries = site.data.galleries; } var pageTitle = page.title; function getCurrentGallery(galleries, pageTitle) { for (let i = 0; i < galleries.length; i++) { if (galleries[i]['name'] == pageTitle) { return galleries[i]; } } } var currentGallery = getCurrentGallery(galleries, pageTitle) var photos = currentGallery.photos; let imageStr = '' for (var i = 0, len = photos.length; i < len; i++) { var photo = photos[i]; <!-- 这儿的网址:https://cdn.jsdelivr.net/gh/321hjd/ImageBed/galleries/ 改为你图片放的位置的网址,比如你用Github图床的话,就改为你图床的网址 --> imageStr += "<a href=\"https://cdn.jsdelivr.net/gh/321hjd/ImageBed/galleries/" + photo + "\"\n" + " class=\"photo-item\" rel=\"example_group\"\n" + " data-fancybox=\"images\">\n" + " <img src=\"https://cdn.jsdelivr.net/gh/321hjd/ImageBed/galleries/" + photo + "\"\n" + " alt=" + photo + ">\n" + " </a>" } %> <!-- " <p class=\"photo-name\">" + photo + "</p>\n" + 文件名先注释掉 --> <!-- 不加密写法 --> <!-- <div class="container"> <div class="photo-wrapper" > <div class="waterfall" id="mygallery"> <%- imageStr %> </div> </div> </div> --> <main class="content" > <!-- 加密写法 --> <div class="container"> <div class="photo-wrapper"> <% if (page.password ) { %> <!-- <script src="/lib/crypto-js.js"></script> --> <script src="/js/crypto-js.js"></script> <script src="/js/gallery-encrypt.js"></script> <div id="hbe-security"> <div class="hbe-input-container"> <input type="password" class="hbe-form-control" id="pass" placeholder="请输入密码查看内容"/> <a href="javascript:;" class="btn-decrypt" id="btn_decrypt">解密</a> </div> </div> <div id="mygallery"> <div class="waterfall" id="encrypt-blog" style="display:none"> <%- aes(imageStr, page.password) %> </div> </div> <% } else { %> <div class="waterfall" id="encrypt-blog"> <%- imageStr %> </div> <% } %> </div> </div> <main> <script src="<%- theme.libs.js.lazyload %>"></script> <script src="<%- theme.libs.js.fancybox %>"></script> <script src="<%- theme.libs.js.justifiedGallery %>"></script> <script> // $(".waterfall").lazyload(); $("a[rel=example_group]").fancybox(); // 不加密写法 // $("#mygallery").justifiedGallery({margins: 5, rowHeight: 150}); $("#encrypt-blog").justifiedGallery({margins: 5, rowHeight: 150}); </script>- 这是
在
source/galleries/下创建相册(比如“壁纸”,用于下面测试)文件夹,并在其下创建index.md,并设置Front-mattery(注意这里的type和layout都是gallery而非galleries,这与前面的gallery.ejs、galleries.ejs相关)--- title: 壁纸 date: 2021-07-19 20:27:35 type: gallery layout: gallery ---在根目录下新建
/source/_data/galleries.json,添加如下内容这里的
name必须和上一步的title一致。另外我的图床图片地址是/galleries/星空/01.jpg,所以前面ejs文件中的url是那样。[ { "name": "壁纸", "cover": "星空/01.jpg", "description": "壁纸", "photos": [ "星空/01.jpg", "星空/02.jpg", "星空/03.jpg", "星空/04.jpg", "星空/05.jpg", "星空/06.jpg", "星空/07.jpg", "星空/08.jpg", "星空/09.jpg", "星空/10.jpg", "星空/11.jpg", "星空/12.jpg", "星空/13.jpg", "星空/14.jpg", "星空/15.jpg", "星空/16.jpg" ] } ]现在编译一下应该可以显示了,但是布局很难看且不能放大。因为还需要两个插件
fancybox和justifiedGallery。(gallery.ejs文件里引用了,但我们没下载这俩插件)打开主题目录下的配置文件
_config.yml,找到存放前端库链接的地方(可搜索libs),将两插件对应的css和js链接写在那儿(不同的版本可以到官网上去找)。css: # 新增插件-用于调整相册布局,可以令图片具有点击放大功能,且布局美观 fancybox: https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.css justifiedGallery: https://cdn.staticfile.org/justifiedGallery/3.7.0/css/justifiedGallery.min.css js: # 新增插件-用于调整相册布局 fancybox: https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.js justifiedGallery: https://cdn.staticfile.org/justifiedGallery/3.7.0/js/jquery.justifiedGallery.min.js现在编译就可以看到比较舒适的相册页面了。
相册加密(
AES加密)具体实现可以参考:使用AES算法加密Hexo相册
在主题根目录下新建目录及文件:
scripts/helpers/encrypt.js/* global hexo */ 'use strict'; const CryptoJS = require('crypto-js'); hexo.extend.helper.register('aes', function(content,password){ content = escape(content); content = CryptoJS.enc.Utf8.parse(content); content = CryptoJS.enc.Base64.stringify(content); content = CryptoJS.AES.encrypt(content, String(password)).toString(); return content; });然后修改
gallery.ejs文件(这一步不需要做,因为前面那段代码其实已经写好了,就是“加密写法”那里)修改
/themes/hexo-theme/matery/source/css/my.css,美化解密按钮.hbe-input-container .btn-decrypt{ display: inline-block; vertical-align: top; width: 120px; height: 32px; line-height: 32px; font-size: 16px; color: #ffffff; background-color: #3f90ff; text-align: center; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; }手动安装
crypto-js插件,到node_modules/crypto-js/下找到crypto-js.js文件,并复制到主题目录下的source/js/下(注意gallery.ejs中的引用目录可能需要修改<script src="/js/crypto-js.js"></script>)npm install crypto-js然后在主题目录的
source/js/下新建gallery-encrypt.js,将我的代码粘进去就好(主要是不知道原来是从哪儿找来的了😢)https://cdn.jsdelivr.net/gh/321hjd/CDN-for-Hexo@CDN-for-Hexo-0.0.3/source/js/gallery-encrypt.js
最后需要在相册比如“壁纸”目录下
index.md中的Front-matter中添加password,自己设置一个密码就好,如:password: 123
4.3 音乐模块
这里我是设置了一个吸底模式的音乐模块和一个单独音乐页面。如果愿意就把音乐页面放在主页,根据注释操作即可。另外注意歌单歌曲过多可能会显示不出来,尽量少一些为好。(建议QQ音乐,网易云经常抽风,不知道为啥)
吸底模式:参考主题目录的
_config.yml注释即可# 是否在首页显示音乐. music: enable: true title: #非吸底模式有效 enable: true show: 听听音乐 autoHide: true # hide automaticaly server: netease #require music platform: netease(网易云), tencent, kugou, xiami, baidu type: playlist #require song, playlist, album, search, artist id: 6862612332 #require song id / playlist id / album id / search keyword fixed: true # 开启吸底模式 autoplay: false # 是否自动播放 theme: '#42b983' loop: 'all' # 音频循环播放, 可选值: 'all', 'one', 'none' order: 'random' # 音频循环顺序, 可选值: 'list', 'random' preload: 'auto' # 预加载,可选值: 'none', 'metadata', 'auto' volume: 0.7 # 默认音量,请注意播放器会记忆用户设置,用户手动设置音量后默认音量即失效 listFolded: true # 列表默认折叠 hideLrc: true # 隐藏歌词 # 提示: server可选netease(网易云音乐),tencent(QQ音乐),kugou(酷狗音乐),xiami(虾米音乐),baidu(百度音乐)。 type可选song(歌曲),playlist(歌单),album(专辑),search(搜索关键字),artist(歌手) id获取示例: 浏览器打开网易云音乐,点击我喜欢的音乐歌单,地址栏有一串数字,playlist的id即为这串数字。单独音乐页面
同样配置主题目录下的
_config.yml# 单独的音乐页面.(注意是musics,与之前的区分开) musics: enable: true url: /music # 这是前面菜单优化部分新建的音乐页面的路径 title: #非吸底模式有效 enable: true show: 听听音乐 server: netease #require music platform: netease, tencent, kugou, xiami, baidu type: playlist #require song, playlist, album, search, artist id: 6862612332 #require song id / playlist id / album id / search keyword fixed: false # 开启吸底模式 autoplay: false # 是否自动播放 theme: '#42b983' loop: 'all' # 音频循环播放, 可选值: 'all', 'one', 'none' order: 'random' # 音频循环顺序, 可选值: 'list', 'random' preload: 'auto' # 预加载,可选值: 'none', 'metadata', 'auto' volume: 0.7 # 默认音量,请注意播放器会记忆用户设置,用户手动设置音量后默认音量即失效 listFolded: false # 列表默认折叠 listMaxHeight: "525px" #列表最大高度将
themes/hexo-theme-matery/layout/_widget/下的music.ejs复制一份命名为musics.ejs然后再在
themes/hexo-theme-matery/layout/下新建musics.ejs文件,粘贴代码:<style type="text/css"> /* don't remove. */ .about-cover { height: 75vh; } </style> <%- partial('_partial/bg-cover') %> <main class="content"> <div id="aboutme" class="container about-container"> <div class="card"> <div class="card-content"> <div class="music-player"> <% if (theme.musics && theme.musics.enable) { %> <%- partial('_widget/musics') %> <style> .bubbles > .particle { /*初始透明度为0*/ opacity: 0; position: absolute; /*初始颜色为荧光色,透明度为0.7*/ background-color: rgba(128,255,0,0.7); /*使用bubbles动画,持续时间18秒,缓慢进入,无限循环*/ animation: bubbles 18s ease-in infinite; border-radius: 100%; } /*css keyframes 动画*/ @keyframes bubbles { 0% { opacity: 0; } 5% { opacity: 1; transform: translate(0, -20%); } /*这里-8000%表示是气泡的8000%*/ 100% { opacity: 0; transform: translate(0, -8000%); } } </style> <!-- 这里让元素宽度100%(和页面等宽) --> <div style="width: 100%; height: 100%; position: relative; bottom: 0px;" class="particletext bubbles"> </div> <script type="text/javascript" src="https://code.jquery.com/jquery-3.1.1.min.js"></script> <script> function bubbles() { $.each($(".particletext.bubbles"), function(){ var bubblecount = ($(this).width()/50)*10; for(var i = 0; i <= bubblecount; i++) { var size = ($.rnd(40,80)/10); //这里的animation-delay很重要,关系到你的特效是否看上去是连续无断层的,上一步中css是18秒,所以这一步中延迟时间就设置成$.rnd(0,180)/10) $(this).append('<span class="particle" style="top:' + $.rnd(20,80) + '%; left:' + $.rnd(0,95) + '%;width:' + size + 'px; height:' + size + 'px;animation-delay: ' + ($.rnd(0,180)/10) + 's;"></span>'); } }); } jQuery.rnd = function(m,n) { m = parseInt(m); n = parseInt(n); return Math.floor( Math.random() * (n - m + 1) ) + m; } bubbles(); </script> <% } %> </div> </div> </div> </div> </main>
4.4 快速导航
这一部分暂时没做完个性化,仅仅是将别人的导航页面copy过来了而已。下面只介绍基本方法。另外其实有两种,一种是真正的导航页面;另一种是简单的浏览器主页。我比较偏向于简约版的后者。
绕过渲染。因为hexo 编译会对主题模板进行渲染之后生成静态页面,但是这个导航的网站本身就是
html文件,因此不需要渲染,那么跳过渲染就需要配置根目录_config.yml中的skip_render项# 指定目录跳过hexo渲染 skip_render: - 'tools/**'工具箱页面在4.1节已经新建完成。
添加WebStackPage导航网站(这是一位名叫 Viggo 的UI设计师的公益项目,开源的静态网站,源码本身就是成品,下载代码之后就可以直接使用。)
从官方项目地址克隆到本地
git clone https://github.com/WebStackPage/WebStackPage.github.io将里面的文件放在博客根目录的
source/tools/下即可这时候编译进入<工具箱>页面应该能看到如下效果

- 然后后续自己修改细节即可
-
- 同上,克隆到本地然后放入
tools/再编译即可。效果如下:

- 同上,克隆到本地然后放入
5. Valine评论模块
5.1 Valine评论模块添加
到leancloud官网注册并创建应用(建议使用国际版,因为后面的
artitalk模块使用国际版更加方便)修改主题目录下配置文件
_config.yml,激活Valinevaline: enable: true appId: XXXXXXXXXXXXXXXXXXXXX # appId和appKey是在leancloud注册后获取的(设置->应用凭证) appKey: XXXXXXXXXXXXXXXXXXXX notify: true verify: true visitor: true avatar: 'mm' # Gravatar style : mm/identicon/monsterid/wavatar/retro/hide pageSize: 10 placeholder: 'just go go' # Comment Box placeholder为添加博主、访客、小伙伴等tag,以及直接通过邮箱或QQ拉取头像,直接使用大佬魔改后的
Valine.min.js文件,并覆盖themes/hexo-theme-matery/source/libs/valine/Valine.min.js然后配置
themes/hexo-theme-matery/layout/_partia/valine.ejs文件<script> new Valine({ el: '#vcomments', enableQQ: '<%= theme.valine.enableQQ %>', appId: '<%- theme.valine.appId %>', appKey: '<%- theme.valine.appKey %>', visitor: '<%- theme.valine.visitor %>' === 'true', avatar: '<%- theme.valine.avatar %>', pageSize: '<%- theme.valine.pageSize %>', lang: '<% if (config.language == "zh-CN") { %>zh-cn<% } else { %>en<% } %>', placeholder: '<%= theme.valine.placeholder %>', meta: ['nick', 'mail'], requiredFields: ['nick','mail'], //必填项 tagMeta: ["博主", "小伙伴", "访客"], master: ["d502ea4605b856df3b9b73bad1e8592e"], // 我的邮箱(MD5加密后)似乎只能用小写,大写无法识别 // friends: // 小伙伴MD5加密后的邮箱 // metaPlaceholder: // 昵称和邮箱无内容时的显示内容 recordIP: true, emojiCDN: '//i0.hdslb.com/bfs/emote/', // 表情title和图片映射 emojiMaps: { //第一个是自定义表情的示例,模仿添加即可 "让我瞅瞅": "https://i.loli.net/2021/07/18/bzTH82kc7KnsBXC.jpg", "tv_doge": "6ea59c827c414b4a2955fe79e0f6fd3dcd515e24.png", "tv_亲亲": "a8111ad55953ef5e3be3327ef94eb4a39d535d06.png", "tv_偷笑": "bb690d4107620f1c15cff29509db529a73aee261.png", "tv_再见": "180129b8ea851044ce71caf55cc8ce44bd4a4fc8.png", "tv_冷漠": "b9cbc755c2b3ee43be07ca13de84e5b699a3f101.png", "tv_发怒": "34ba3cd204d5b05fec70ce08fa9fa0dd612409ff.png", "tv_发财": "34db290afd2963723c6eb3c4560667db7253a21a.png", "tv_可爱": "9e55fd9b500ac4b96613539f1ce2f9499e314ed9.png", "tv_吐血": "09dd16a7aa59b77baa1155d47484409624470c77.png", "tv_呆": "fe1179ebaa191569b0d31cecafe7a2cd1c951c9d.png", "tv_呕吐": "9f996894a39e282ccf5e66856af49483f81870f3.png", "tv_困": "241ee304e44c0af029adceb294399391e4737ef2.png", "tv_坏笑": "1f0b87f731a671079842116e0991c91c2c88645a.png", "tv_大佬": "093c1e2c490161aca397afc45573c877cdead616.png", "tv_大哭": "23269aeb35f99daee28dda129676f6e9ea87934f.png", "tv_委屈": "d04dba7b5465779e9755d2ab6f0a897b9b33bb77.png", "tv_害羞": "a37683fb5642fa3ddfc7f4e5525fd13e42a2bdb1.png", "tv_尴尬": "7cfa62dafc59798a3d3fb262d421eeeff166cfa4.png", "tv_微笑": "70dc5c7b56f93eb61bddba11e28fb1d18fddcd4c.png", "tv_思考": "90cf159733e558137ed20aa04d09964436f618a1.png", "tv_惊吓": "0d15c7e2ee58e935adc6a7193ee042388adc22af.png", "tv_打脸": "56ab10b624063e966bfcb76ea5dc4794d87dfd47.png", "tv_抓狂": "fe31c08edad661d63762b04e17b8d5ae3c71a757.png", "tv_抠鼻": "c666f55e88d471e51bbd9fab9bb308110824a6eb.png", "tv_斜眼笑": "911f987aa8bc1bee12d52aafe62bc41ef4474e6c.png", "tv_无奈": "ea8ed89ee9878f2fece2dda0ea8a5dbfe21b5751.png", "tv_晕": "5443c22b4d07fb1907ccc610c8e6db254f2461b7.png", "tv_流汗": "cead1c351ab8d79e9f369605beb90148db0fbed3.png", "tv_流泪": "7e71cde7858f0cd50d74b0264aa26db612a8a167.png", "tv_流鼻血": "c32d39db2737f89b904ca32700d140a9241b0767.png", "tv_点赞": "f85c354995bd99e28fc76c869bfe42ba6438eff4.png", "tv_生气": "26702dcafdab5e8225b43ffd23c94ac1ff932654.png", "tv_生病": "8b0ec90e6b86771092a498c54f09fc94621c1900.png", "tv_疑问": "0793d949b18d7be716078349c202c15ff166f314.png", "tv_白眼": "c1d59f439e379ee50eef488bcb5e5378e5044ea4.png", "tv_皱眉": "72ccad6679fea0d14cce648b4d818e09b8ffea2d.png", "tv_目瞪口呆": "0b8cb81a68de5d5365212c99375e7ace3e7891b7.png", "tv_睡着": "8b196675b53af58264f383c50ad0945048290b33.png", "tv_笑哭": "1abc628f6d4f4caf9d0e7800878f4697abbc8273.png", "tv_腼腆": "89712c0d4af73e67f89e35cbc518420380a7f6f4.png", "tv_色": "61822c7e9aae5da76475e7892534545336b23a6f.png", "tv_调侃": "4bc022533ef31544ca0d72c12c808cf4a1cce3e3.png", "tv_调皮": "b9c41de8e82dd7a8515ae5e3cb63e898bf245186.png", "tv_鄙视": "6e72339f346a692a495b123174b49e4e8e781303.png", "tv_闭嘴": "c9e990da7f6e93975e25fd8b70e2e290aa4086ef.png", "tv_难过": "87f46748d3f142ebc6586ff58860d0e2fc8263ba.png", "tv_馋": "fc7e829b845c43c623c8b490ee3602b7f0e76a31.png", "tv_鬼脸": "0ffbbddf8a94d124ca2f54b360bbc04feb6bbfea.png", "tv_黑人问号": "45821a01f51bc867da9edbaa2e070410819a95b2.png", "tv_鼓掌": "1d21793f96ef4e6f48b23e53e3b9e42da833a0f6.png" // ... 更多表情 } }); </script>
5.2 增强评论系统
功能:
- 支持评论回复提醒(微信/QQ/邮件)
- 支持@对方时给对方发送邮件并自带主题
在
leancloud上部署评论增强系统:Valine-Admin-server(使用的是小康改版)打开
leancloud,云引擎->WEB->部署->部署项目->Git部署->配置Git,然后将`https://github.com/kaze0617/Valine-Admin-Server 填入其中,保存->部署项目->部署。
配置环境变量:云引擎->设置->自定义环境变量
我只设置了邮件和微信提醒,没用QQ的。设置完成后再次部署生效。
变量 示例 说明 SITE_NAME hjd’blog [必填]博客名称 SITE_URL https://321hjd.github.io/ [必填]首页地址 SMTP_SERVICE QQ 邮件服务提供商,支持 QQ、163、126、Gmail以及更多 SMTP_USER 2857126002@qq.com [必填]SMTP登录用户 SMTP_PASS xxx [必填]SMTP登录密码(QQ邮箱可通过设置-账户-SMTP服务-生成授权码获取) SENDER_NAME hjd’blog [必填]发件人 SENDER_EMAIL 2857126002@qq.com [必填]发件邮箱 BLOGGER_EMAIL 2857126002@qq.com [可选]博主通知收件地址,默认使用SENDER_EMAIL SCKEY xxx Server酱 SCKEY 用于微信通知 DISABLE_EMAIL false 如果为true,关闭邮件通知 TEMPLATE_NAME custom2 设置回复邮件的主题样式 微信提醒还需要按照Server酱-消息通道 的指示注册企业微信并创建应用才行
博主回复别人后的邮件提醒效果:

有人评论时的微信提醒效果

后台管理。增删改评论在
leancloud的数据存储->结构化数据->Comment处操作即可防止休眠(如果不设置,每过一段时间重新部署,才能收到评论提醒)。需要购买域名,具体请参考:Valine评论系统详解
6. 说说模块Artitalk
在leancloud官网(建议使用国际版,否则需要配置
serverurl)注册并绑定手机号和邮箱。然后创建应用(与Valine不是同一个)注意下面一定要设置好(尤其是权限),否则可能发不了说说,或者任意人都能在你的博客上修改或发表说说。
- 在
结构化数据中创建class,命名为shuoshuo - 在你新建的应用中找到
结构化数据下的用户。点击添加用户,输入想用的用户名及密码。(这就是你用来发说说的账号) - 回到
结构化数据中,点击class下的shuoshuo。找到权限,在Class 访问权限中将add_fields以及create权限设置为指定用户,输入你刚才输入的用户名会自动匹配。为了安全起见,将delete和update也设置为跟它们一样的权限。(注意一定要等匹配后看到显示了objectId才没问题) - 然后新建一个名为
atComment的class,权限默认 - 点击
class下的_User添加列,列名称为img,默认值填上你这个账号想要用的发布说说的头像url,这一项不进行配置,说说头像会显示为默认头像 —— Artitalk 的 logo。 - 将
_User中的权限全部调为指定用户,或者数据创建者,为了保证不被篡改用户数据已达到强制发布说说
- 在
下载
Artitalk并放入组件git clone --depth 2 git@github.com:ArtitalkJS/Artitalk.git- 在
themes/hexo-theme-matery/source/libs/下新建artitalk文件夹。将下载所得Artitalk中dist下的组件代码(两个文件:artitalk.min.js和artitalk.min.css)全部放入artitalk/下
- 在
引入该模块。修改主题配置文件
_config.yml,在libs下加入刚刚的两个文件,如:libs: css: artitalk: /libs/artitalk/artitalk.min.css js: artitalk: /libs/artitalk/artitalk.min.js引入
css。在themes/hexo-theme-matery/layout/_partial/head.ejs的尾部对应位置引入css(参照其它代码即可)<link rel="stylesheet" type="text/css" href="<%- theme.jsDelivr.url %><%- url_for(theme.libs.css.artitalk) %>">模块准备。在主题目录下
/layout/目录新建一个artitalk.ejs 文件<%- partial('_partial/bg-cover') %> <style ype="text/css"> #pubShuo { margin-right: 5px; } #operare_artitalk .shuoshuo_input_log { outline-style: none; margin-top: 5px; border: 1px solid #ccc; border-radius: 6px; padding: 8px 16px; font-size: 12px; background-color: transparent; color: #0bb7fbd6; width: 70%; height: 28px; margin-left: 10px; } #artitalk_main { margin-top: 5px ; margin-left: 5%; margin-right: 5%; } #lazy{ margin-top: 40px; } #artitalk_main .cbp_tmtimeline > li .cbp_tmlabel::after { right: 100%; border: solid transparent; z-index: -1; content: " "; height: 0; width: 0; position: absolute; pointer-events: none; border-right-color: #0bb7fbd6 ; border-width: 10px; top: 4px; } </style> <script src="<%- theme.jsDelivr.url %><%- url_for(theme.libs.js.artitalk) %>"></script> <article id="articles11" class="container chip-container"> <div class="row "> <div class=" card"> <div class="card-content" > <div class="tag-title center-align"> <i class="fas fa-pen-alt"></i> 说说 </div> <div id="artitalk_main"></div> </div> </div> </div> </article> <script> new Artitalk({ appId: "<%= theme.artitalk.appId %>", appKey: "<%= theme.artitalk.appKey %>", <% if (theme.artitalk.serverURL) { %> serverURL: "<%= theme.artitalk.serverURL %>", <% } %> <% if (theme.artitalk.lang) { %> lang: "<%= theme.artitalk.lang %>", <% } %> <% if (theme.artitalk.pageSize) { %> pageSize: "<%= theme.artitalk.pageSize %>", <% } %> <% if (theme.artitalk.shuoPla) { %> shuoPla: "<%= theme.artitalk.shuoPla %>", <% } %> <% if (theme.artitalk.avatarPla) { %> avatarPla: "<%= theme.artitalk.avatarPla %>", <% } %> <% if (theme.artitalk.motion == 0) { %> motion: 0, <% } else { %> motion: 1, <% } %> <% if (theme.artitalk.bgImg) { %> bgImg: "<%= theme.artitalk.bgImg %>", <% } %> <% if (theme.artitalk.color1) { %> color1: "<%= theme.artitalk.color1 %>", <% } %> <% if (theme.artitalk.color2) { %> color2: "<%= theme.artitalk.color2 %>", <% } %> <% if (theme.artitalk.color3) { %> color3: "<%= theme.artitalk.color3 %>", <% } %> <% if (theme.artitalk.cssUrl) { %> cssUrl: "<%= theme.artitalk.cssUrl %>", <% } %> atEmoji: { baiyan: "https://cdn.jsdelivr.net/gh/Artitalk/Artitalk-emoji/baiyan.png", bishi: "https://cdn.jsdelivr.net/gh/Artitalk/Artitalk-emoji/bishi.png", bizui: "https://cdn.jsdelivr.net/gh/Artitalk/Artitalk-emoji/bizui.png", chan: "https://cdn.jsdelivr.net/gh/Artitalk/Artitalk-emoji/chan.png", daku: "https://cdn.jsdelivr.net/gh/Artitalk/Artitalk-emoji/daku.png", dalao: "https://cdn.jsdelivr.net/gh/Artitalk/Artitalk-emoji/dalao.png", dalian: "https://cdn.jsdelivr.net/gh/Artitalk/Artitalk-emoji/dalian.png", dianzan: "https://cdn.jsdelivr.net/gh/Artitalk/Artitalk-emoji/dianzan.png", doge: "https://cdn.jsdelivr.net/gh/Artitalk/Artitalk-emoji/doge.png", facai: "https://cdn.jsdelivr.net/gh/Artitalk/Artitalk-emoji/facai.png", fadai: "https://cdn.jsdelivr.net/gh/Artitalk/Artitalk-emoji/fadai.png", fanu: "https://cdn.jsdelivr.net/gh/Artitalk/Artitalk-emoji/fanu.png", }, }) </script>在主题配置文件中添加
artitalk配置artitalk: enable: true appId: # 刚刚创建应用的AppID appKey: # 刚刚创建应用的AppKey lang: zh # 语言设置,zh为汉语,en为英语,es为西班牙语。默认为汉语 pageSize: 10 #每页说说的显示数量 # shuoPla: #在编辑说说的输入框中的占位符 avatarPla: # https://cdn.jsdelivr.net/gh/321hjd/321hjd.github.io/source/medias/avatar.jpg #自定义头像url的输入框的占位符 # motion: #加载动画的开关,1为开,0为关,默认为开 # bgImg: #说说输入框背景图片url color1: linear-gradient(45deg, rgb(109, 208, 242) 15%, rgb(245, 200, 190) 85%) #说说背景颜色1&按钮颜色1 color2: linear-gradient(45deg, rgb(109, 208, 242) 15%, rgb(245, 200, 190) 85%) #说说背景颜色2&按钮颜色2 color3: black #说说字体颜色创建说说页面并添加链接。在第三部分的4.1节已经创建完成。
现在编译再进入说说页面应该就可以了。
参考链接
- Hexo+Github博客搭建完全教程
- Matery优化(二)
- hexo(matery)背景、滚动条优化+增加点击跳评论
- hexo-theme-matery官方文档
- Matery主题搭建与优化教程超详细解析
- Luckysec博客源码
- 使用 PicGo+Github 搭建免费图床
- 使用AES算法加密Hexo相册
- Matery 添加WebStackPage导航网站
- Valine评论系统详解
- Valine 评论之 Valine-admin 配置攻略
- Hexo 博客 Matery 主题添加 ArtiTalk 说说模块
- Artitalk官方文档
四、性能优化
1. 图片懒加载
安装图片懒加载插件:hexo-lazyload-image
npm install hexo-lazyload-image --save在博客根目录下的配置文件末尾添加
# 懒加载配置 lazyload: enable: true onlypost: false # 是否只对文章的图片做懒加载 loadingImg: /medias/loading.gif # 即放一个表示加载中的图片(这个图片得自己去找一个放在themes/hexo-theme-matery/source/medias/目录下)一般情况下懒加载会和gallery插件会发生冲突,结果可能就是点开图片,左翻右翻都是loading image。matery主题的解决方案是:修改
/themes/matery/source/js中的matery.js文件,在第108行加上$(document).find('img[data-original]').each(function(){ $(this).parent().attr("href", $(this).attr("data-original")); });可能还有个小问题,首页的logo点击会直接打开logo图,而不是跳到首页。解决方案:打开
/themes/matery/layout/_partial/header.ejs文件,在
img和span的两个头加个div:<div class="brand-logo"> <a href="<%- url_for() %>" class="waves-effect waves-light"> <div> <% if (theme.logo !== undefined && theme.logo.length > 0) { %> <img src="<%= theme.logo %>" class="logo-img" alt="LOGO"> <% } %> <span class="logo-span"><%- config.title %></span> </div> </a> </div>懒加载优化(即提前加载图片,其实也可以不做)。具体请参考:Hexo进阶之各种优化
2. 跳转页面载入动画
在博客根目录下新建文件夹
scripts(之前加密相册时已经建好了其实),然后在该目录下新建loading-pages.js,填入代码即可/* global hexo */ "use strict"; hexo.extend.filter.register('after_render:html', function (htmlContent) { const injectHead = `<style type="text/css" lang="css"> #loading-container{ position: fixed; top: 0; left: 0; min-height: 100vh; width: 100vw; z-index: 9999; display: flex; flex-direction: column; justify-content: center; align-items: center; background: #FFF; text-align: center; /* loader页面消失采用渐隐的方式*/ -webkit-transition: opacity 1s ease; -moz-transition: opacity 1s ease; -o-transition: opacity 1s ease; transition: opacity 1s ease; } .loading-image{ width: 120px; height: 50px; transform: translate(-50%); } .loading-image div:nth-child(2) { -webkit-animation: pacman-balls 1s linear 0s infinite; animation: pacman-balls 1s linear 0s infinite } .loading-image div:nth-child(3) { -webkit-animation: pacman-balls 1s linear .33s infinite; animation: pacman-balls 1s linear .33s infinite } .loading-image div:nth-child(4) { -webkit-animation: pacman-balls 1s linear .66s infinite; animation: pacman-balls 1s linear .66s infinite } .loading-image div:nth-child(5) { -webkit-animation: pacman-balls 1s linear .99s infinite; animation: pacman-balls 1s linear .99s infinite } .loading-image div:first-of-type { width: 0; height: 0; border: 25px solid #49b1f5; border-right-color: transparent; border-radius: 25px; -webkit-animation: rotate_pacman_half_up .5s 0s infinite; animation: rotate_pacman_half_up .5s 0s infinite; } .loading-image div:nth-child(2) { width: 0; height: 0; border: 25px solid #49b1f5; border-right-color: transparent; border-radius: 25px; -webkit-animation: rotate_pacman_half_down .5s 0s infinite; animation: rotate_pacman_half_down .5s 0s infinite; margin-top: -50px; } @-webkit-keyframes rotate_pacman_half_up {0% {transform: rotate(270deg)}50% {transform: rotate(1turn)}to {transform: rotate(270deg)}} @keyframes rotate_pacman_half_up {0% {transform: rotate(270deg)}50% {transform: rotate(1turn)}to {transform: rotate(270deg)}} @-webkit-keyframes rotate_pacman_half_down {0% {transform: rotate(90deg)}50% {transform: rotate(0deg)}to {transform: rotate(90deg)}} @keyframes rotate_pacman_half_down {0% {transform: rotate(90deg)}50% {transform: rotate(0deg)}to {transform: rotate(90deg)}} @-webkit-keyframes pacman-balls {75% {opacity: .7}to {transform: translate(-100px, -6.25px)}} @keyframes pacman-balls {75% {opacity: .7}to {transform: translate(-100px, -6.25px)}} .loading-image div:nth-child(3), .loading-image div:nth-child(4), .loading-image div:nth-child(5), .loading-image div:nth-child(6){ background-color: #49b1f5; width: 15px; height: 15px; border-radius: 100%; margin: 2px; width: 10px; height: 10px; position: absolute; transform: translateY(-6.25px); top: 25px; left: 100px; } .loading-text{ margin-bottom: 20vh; text-align: center; color: #2c3e50; font-size: 2rem; box-sizing: border-box; padding: 0 10px; text-shadow: 0 2px 10px rgba(0,0,0,0.2); } @media only screen and (max-width: 500px) { .loading-text{ font-size: 1.5rem; } } .fadeout { opacity: 0; filter: alpha(opacity=0); } /* logo出现动画 */ @-webkit-keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}} @keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);}} </style> <script> (function () { const loaded = function(){ setTimeout(function(){ const loader = document.getElementById("loading-container"); loader.className="fadeout" ;//使用渐隐的方法淡出loading page // document.getElementById("body-wrap").style.display="flex"; setTimeout(function(){ loader.style.display="none"; },1000); },1000);//强制显示loading page 1s }; loaded(); })() </script>`; const injectBody = ` <div id="loading-container"> <p class="loading-text">玩命加载中 . . . </p> <div class="loading-image"> <div></div> <div></div> <div></div> <div></div> <div></div> </div> </div>`; if (/<\/head>/gi.test(htmlContent)) { let lastIndex = htmlContent.lastIndexOf('</head>'); htmlContent = htmlContent.substring(0, lastIndex) + injectHead + htmlContent.substring(lastIndex, htmlContent.length); } if (/<body>/gi.test(htmlContent)) { let index = htmlContent.indexOf('<body>'); htmlContent = htmlContent.substring(0, index) + injectBody + htmlContent.substring(index, htmlContent.length); } return htmlContent; }, 1);
3. 新建文章时自动打开本地md编辑器
在博客根目录下的
scripts/下新建auto_open.js,添加代码:var spawn = require('child_process').exec; // Hexo 2.x 用户复制这段 //hexo.on('new', function(path){ //spawn('start "markdown编辑器绝对路径.exe" ' + path); //}); // Hexo 3 用户复制这段 hexo.on('new', function(data){ spawn('start "D:\Program Files\Typora\Typora.exe" ' + data.path); });- 注意:
Typora.exe的路径根据实际情况修改。
- 注意:
4. jsDelivr + GitHub实现免费CDN加速
CDN简介及原理:如何使用jsDelivr+Github 实现免费CDN加速?jsDelivr:免费、快速和可信赖的
CDN加速服务实现
新建
GitHub仓库(我的叫CDN-for-Hexo)将仓库克隆到本地:
git clone git@github.com:{username}/{repo}.git将需要加速的资源文件复制到该本地仓库并上传到
GitHub仓库(Hexo的静态资源css、js、图片等)。我是将主题下的整个source文件夹都传上去了。git add . # 添加所有文件到暂存区 git status # 查看状态 git commit -m "CDN加速,第一次提交" # 将文件提交到仓库 git push # 推送至远程仓库点击右边的
release发布版本。如CDN-for-Hexo-1.0
修改主题目录下的配置文件,通过
jsDelivr引用资源。如:libs: css: matery: https://cdn.jsdelivr.net/gh/321hjd/CDN-for-Hexo@b4706a7/source/css/matery.css mycss: https://cdn.jsdelivr.net/gh/321hjd/CDN-for-Hexo@b4706a7/source/css/my.css- 引用方式为:
https://cdn.jsdelivr.net/gh/你的用户名/你的仓库名@发布的版本号/文件路径
经过测试,不写版本号似乎不能引用到最新资源。需要引用最新版的话,最好是
仓库名@版本号如CDN-for-Hexo@b4706a7而非CDN-for-Hexo@CDN-for-Hexo-1.0。注:
jsdelivr可以自动帮你生成.min版的js和css,所以你在设置js及css路径中可以直接写.min.xxx- 引用方式为:
修改完成后再编译部署,会发现访问速度快了很多~
5. 文章永久链接优化
为什么要生成唯一永久文章链接:确保在我们修改了
Front-matter内的博客标题title或创建日期date字段之后而不会改变链接地址。安装插件:
npm install hexo-abbrlink --save配置。修改博客根目录配置文件的
permalink属性permalink: posts/:abbrlink.html # 此处可以自己设置,也可以直接使用 :/abbrlink abbrlink: alg: crc32 #算法: crc16(default) and crc32 rep: hex #进制: dec(default) and hex生成完后,原
md文件的Front-matter 内会增加abbrlink字段,值为生成的ID 。至此我们的文章链接将变为:https://{username}.github.io/posts/{abbrlink_id}.html引发的问题:插入图片的路径发生变化,前面新增了一个对应文章的
abbrlink_id目录分析:生成图片链接时自己把
abbrlink加上,是因为原来hexo的设计思想(因为post_asset_folder的存在)是将文档的图片放置在同名文件夹下,然后将md转换为html同样以该结构存储,即- 根目录(按原来的结构应该是/public/year/month/day/) - MDfilename.html - MDfilename_folder - xxx.jpg - ...解决方案:修改
/node_modules/hexo-asset-image/index.js中的两行(即自己把abbrlink加入到image的生成路径中)- 在源码的12行附近
var link = data.permalink;这一行的下面,添加 一行var abbrlink = data.abbrlink(即自己定义一个变量abbrlink获取生成的abbrlink) - 在源码的51行附近,将原来的
$(this).attr('src' , config.root + link + src);改为$(this).attr('src' , config.root + link + abbrlink + '/' + src);
- 在源码的12行附近