Hexo介绍
Hexo 是一个基于 Node.js 的快速、简洁且高效的博客框架,用 Markdown 写作,插件和主题多,可快速搭建个人博客。
安装 Node.js
Hexo 的运行环境
https://nodejs.org/zh-cn/download
选择LTS稳定正式版
检查是否安装成功
安装 Git
https://git-scm.com/downloads
检查是否安装成功
安装 Hexo
https://hexo.io/zh-cn/
npm 全局安装 Hexo
检查是否安装成功
搭建 Hexo 博客
初始化博客
安装依赖
启动本地服务器
访问 http://localhost:4000 查看
初始化后文件结构
1 2 3 4 5 6 7 8
| 自定义文件名 ├── _config.yml Hexo配置文件 ├── package.json #项目信息 ├── scaffolds ├── source #存放页面和文章,_posts里存放文章 | ├── _drafts | └── _posts └── themes #存放主题
|
核心操作命令
创建新文章
创建新页面
hexo clean 清除缓存和生成文件
hexo generate 生成静态文件
hexo server 启动本地服务器
hexo deploy 部署到服务器
修改后内容后,可以使用以下命令清理缓存重新生成静态文件并启动服务器
1
| hexo cl && hexo g && hexo s
|
修改配置
网站配置
1 2 3 4 5 6 7 8
| # Site title: KZero's Blog #网站标题 subtitle: 'Accumulation record' # 网站副标题 description: '好记性不如烂键盘' # 网站描述 keywords: KZero Blog # 网站关键字,支持多个关键词 author: CodeKZero # 您的名字 language: en #zh-CN # 网站使用的语言 timezone: ''
|
URL配置
highlight配置(新版本可能缺少 enable: true 而无法使用)
1 2 3 4 5 6
| highlight: line_number: true auto_detect: false tab_replace: '' wrap: true hljs: false
|
修改
1 2 3 4 5 6 7
| highlight: enable: true line_number: true auto_detect: false tab_replace: '' wrap: true hljs: false
|
Live2D配置
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
| # Live2D # https://github.com/EYHN/hexo-helper-live2d live2d: enable: true scriptFrom: local # 默认 pluginRootPath: live2dw/ # 插件在站点上的根目录(相对路径) pluginJsPath: lib/ # 脚本文件相对与插件根目录路径 pluginModelPath: assets/ # 模型文件相对与插件根目录路径 # scriptFrom: jsdelivr # jsdelivr CDN # scriptFrom: unpkg # unpkg CDN # scriptFrom: https://cdn.jsdelivr.net/npm/live2d-widget@3.x/lib/L2Dwidget.min.js # 你的自定义 url tagMode: false # 标签模式, 是否仅替换 live2d tag标签而非插入到所有页面中 debug: false # 调试, 是否在控制台输出日志 model: # use: live2d-widget-model-hijiki # npm-module package name use: PLT #wanko # 博客根目录/live2d_models/ 下的目录名 # use: ./wives/wanko # 相对于博客根目录的路径 # use: https://cdn.jsdelivr.net/npm/live2d-widget-model-wanko@1.0.5/assets/wanko.model.json # 你的自定义 url display: position: right width: 280 height: 426 superSample: 2 #超级样本 hOffset: -82 #偏移量 vOffset: -82 #垂直偏移 # 互动增强配置 # click: true # 开启点击互动 # mouseover: true # 开启鼠标悬停互动 # auto: true # 自动播放待机动作 # hover: true # 显示互动提示文字 # hoverTips: # 自定义提示文字 # default: "想和我玩吗?" # touch: "哎呀!别碰我!" # click: "点击我有惊喜哦~" mobile: show: false # 手机中是否展示 scale: 0.6 # 移动设备上的缩放 hHeadPos: 0.2 # 在移动设备上水平方向头部位置调整 (百分比,影响模型在屏幕上的水平定位) vHeadPos: 0.1 # 在移动设备上垂直方向头部位置调整 (百分比,影响模型在屏幕上的垂直定位) # react: # opacityDefault: 0.7 # 看板娘默认的不透明度 (0 完全透明 - 1 完全不透明) # opacityOnHover: 0.8 # 当鼠标悬停在看板娘上时的不透明度
|
搜索配置
1 2 3 4 5 6
| # 搜索功能 search: path: search.xml field: post format: html limit: 10000
|
Hexo NexT 配置
安装 NexT 主题
根目录
1
| git clone https://github.com/next-theme/hexo-theme-next.git themes/next
|
_config.yml 修改
theme/next/_config.yml 修改
1 2 3 4 5
| # Schemes scheme: Muse #scheme: Mist #scheme: Pisces #scheme: Gemini
|
修改
1 2 3 4 5
| # Schemes # scheme: Muse #scheme: Mist #scheme: Pisces scheme: Gemini
|
修改配置
添加自定义页面
添加archives/categories/tags/about/links页面
添加归档、分类、标签、关于我、友情链接页面
修改配置
theme/next/_config.yml 修改
1 2 3 4 5 6 7 8 9 10
| menu: home: / || fa fa-home # 首页 categories: /categories/ || fa fa-th # 分类系统 archives: /archives/ || fa fa-archive #chart-diagram #archive # 文章归档 tags: /tags/ || fa fa-tags # 标签云 about: /about/ || fa fa-robot #user # 关于页面 Friend: /links/ || fa fa-user-group #users # 友情链接 # schedule: /schedule/ || fa fa-calendar # 日程表 # sitemap: /sitemap.xml || fa fa-sitemap # 站点地图 # commonweal: /404/ || fa fa-heartbeat # 公益404页
|
添加 archives 页面
开启后,默认自带不用操作
添加 categories 页面
1
| hexo new page "categories"
|
source/categories/index.md 修改
1 2 3 4 5 6
| --- title: Categories date: 2025-06-16 16:07:13 type: categories comments: false ---
|
添加 tage 页面
source/tags/index.md 修改
1 2 3 4 5 6
| --- title: Tags date: 2025-06-16 16:07:40 type: tags comments: false ---
|
添加 about 页面
source/about/index.md 修改
1 2 3 4 5 6 7 8 9 10 11 12
| --- title: About Me date: 2025-06-16 16:07:45 type: about ---
Hello~ I'm KZero
来自福建,是个爱折腾爱探索的动漫日剧爱好者,热衷于各种科技产品和好用效率的软件,喜欢简洁舒适科技的御宅生活。 喜欢编程,虽然整天研究一些无用的东西,但每天过充实而快乐。 喜欢游戏,Apex、守望先锋、星际争霸、冒险岛... 喜欢运动,户外、骑行、篮球、乒乓球...
|
添加 links 页面
source/links/index.md 修改
1 2 3 4 5 6 7 8 9 10 11 12
| --- title: Friend Links date: 2025-06-16 16:07:54 type: links ---
欢迎在下面留言申请友情链接~格式如下
> 名称:KZero 描述:Coding / Hiking / Photog / Music 博客地址:http://zoiii.cn 头像地址:http://zoiii.cn/img/avatar.gif
|
theme/next/layout/ 新建 links.njk(可修改友链样式)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| {% block content %} {######################} {### LINKS BLOCK ###} {######################}
<div id="links"> <style>
#links{ margin-top: 5rem; }
.links-content { width: 100%; }
.link-navigation{ overflow: hidden; display: inline-block; padding: 0 0 7px; }
.card { height: 70px; width: 300px; display: block; color: #666; line-style-type: none; text-decoration: none; box-shadow: 0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12); transition: box-shadow .25s cubic-bezier(.4, 0, .2, 1); margin: 10px; float: left; border: 0; }
.card:hover { text-decoration: none; box-shadow: 0 5px 5px -3px rgba(0, 0, 0, .2), 0 8px 10px 1px rgba(0, 0, 0, .14), 0 3px 14px 2px rgba(0, 0, 0, .12); }
.card .ava { float: left; height: 70px; width: 70px; margin: 0; }
.card-header { overflow: hidden; height: 70px; width: 230px; margin-left: 70px; font-size: 15px; }
.nickname { text-align: center; height: 25px; width: 100%; line-height: 12px; margin: 14px 0 0; } .info { text-align: center; height: 20px; width: 100%; margin: 0; line-height: 12px; color: #777; font-size: 12px; } </style> <div class="links-content"> <div class="link-navigation">
{% for link in theme.mylinks %}
<a href="{{ link.site }}" target="_blank" class="card"> <img class="ava" src="{{ link.avatar }}"/> <div class="card-header"> <div class="nickname">{{ link.nickname }}</div> <div class="info">{{ link.info }}</div> </div> </a>
{% endfor %}
</div> {{ page.content }} </div> </div>
{##########################} {### END LINKS BLOCK ###} {##########################} {% endblock %}
|
theme/next/layout/page.njk 引入
1 2 3
| <!-- 友情链接--> {%- elif page.type === 'links' and not page.title %} {{- __('title.links') + page_title_suffix }}
|
引入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| {% block title %} {%- set page_title_suffix = ' | ' + title %}
{%- if page.type === 'categories' and not page.title %} {{- __('title.category') + page_title_suffix }} {%- elif page.type === 'tags' and not page.title %} {{- __('title.tag') + page_title_suffix }} {%- elif page.type === 'schedule' and not page.title %} {{- __('title.schedule') + page_title_suffix }} <!-- 友情链接--> {%- elif page.type === 'links' and not page.title %} {{- __('title.links') + page_title_suffix }}
{%- else %} {{- page.title + page_title_suffix }} {%- endif %} {% endblock %}
|
和
1 2 3
| <!-- 友情链接--> {% elif page.type === 'links' %} {%- include 'links.njk' -%}
|
引入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <div class="post-body{% if page.direction and page.direction.toLowerCase() === 'rtl' %} rtl{% endif %}"> {%- if page.type === 'tags' %} {%- include '_partials/page/tags.njk' -%} {% elif page.type === 'categories' %} {%- include '_partials/page/categories.njk' -%}
<!-- 友情链接--> {% elif page.type === 'links' %} {%- include 'links.njk' -%}
{% elif page.type === 'schedule' %} {%- include '_partials/page/schedule.njk' -%} {% else %} {{ page.content }} {%- endif %} </div>
|
theme/next/_config.yml 添加
1 2 3 4 5 6 7
| # 友链 mylinks:
- nickname: # 名字 info: # 描述 site: # 网站地址 avatar: # 头像
|
添加搜索功能
theme/next/_config.yml 修改
1 2
| local_search: enable: true
|
安装搜索插件
1
| npm install hexo-generator-searchdb --save
|
添加 Live2D
根目录
1
| npm install hexo-helper-live2d --save
|
_config.yml 添加
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
| # Live2D ## https://github.com/EYHN/hexo-helper-live2d live2d: enable: true #是否启用 scriptFrom: local # 脚本来源,可以是local或jsdelivr等CDN pluginRootPath: live2dw/ # 插件在站点上的根目录(相对路径) pluginJsPath: lib/ # 插件JS目录 pluginModelPath: assets/ # 插件模型目录 # scriptFrom: jsdelivr # jsdelivr CDN # scriptFrom: unpkg # unpkg CDN # scriptFrom: https://cdn.jsdelivr.net/npm/live2d-widget@3.x/lib/L2Dwidget.min.js # 你的自定义 url tagMode: false # 标签模式, 是否仅替换 live2d tag标签而非插入到所有页面中 debug: false # 调试模式, 是否在控制台输出日志 model: # use: live2d-widget-model-hijiki # npm-module package name use: PLT #wanko # 博客根目录/live2d_models/ 下的目录名 # use: ./wives/wanko # 相对于博客根目录的路径 # use: https://cdn.jsdelivr.net/npm/live2d-widget-model-wanko@1.0.5/assets/wanko.model.json # 你的自定义 url display: position: right width: 280 height: 426 superSample: 2 #超级样本 hOffset: -82 #偏移量 vOffset: -82 #垂直偏移 mobile: show: true # 手机中是否展示 scale: 0.6 # 移动设备上的缩放 hHeadPos: 0.2 vHeadPos: 0.618 react: opacityDefault: 0.7 opacityOnHover: 0.8
|
根目录下新建 live2dw 文件夹用来存放Live2D模型,通过配置文件选取模型
添加 APlayer
添加 APlayer
找个地方下载APlayer只需要里面dist文件
1
| git clone https://github.com/DIYgod/APlayer
|
aplayer/dist 里新建 music.js 添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const ap = new APlayer({ container: document.getElementById('aplayer'), fixed: true, autoplay: false, loop: 'all', volume: 0.7, //默Ï认音量Ï listFolded: true, listMaxHeight: 60, audio: [ { name: "Welcome to Chew Chew", artist: 'Asteria', url: 'https://music.163.com/song/media/outer/url?id=435403078.mp3', cover: 'https://p1.music.126.net/Epju_XiNiSWoafctIg68JQ==/17940731230636690.jpg', } ] });
|
music.js 内容可根据:APlayer官方文档 进行配置
把 dist 放入 theme/next/source
在 hexo-blog\themes\next\layout_layout.njk 在body标签后 –>
1 2 3 4 5
| <!-- 添加aplayer --> <link rel="stylesheet" href="/dist/APlayer.min.css"> <div id="aplayer"></div> <script type="text/javascript" src="/dist/APlayer.min.js"></script> <script type="text/javascript" src="/dist/music.js"></script>
|
网易云音乐链接
网易云音乐复制歌曲链接
1
| https://music.163.com/song?id=取这里的id值&userid=423945766
|
链接模版:
1
| https://music.163.com/song/media/outer/url?id=把id值添加到这里.mp3
|
获取头像F12选取链接
CloudflareR2 获取音乐链接
下载好 .mp3 音乐
网易云音乐下载音乐有些可能是 ncm 格式
音频 ncm 格式转 mp3
https://www.zhuanhuanyun.cn/?to=.zh-warp
Cloudflare R2:https://dash.cloudflare.com/
R2 Object Storage –> Create bucket
Bucket name: music
Location: Automatic –> Provide a location hint (optional) –Asia-Pacific (APAC)
Default Storage Class –> Standard
Settings –> Public Development URL –> Enable -> 输入allow –> Allow
Objects –> select from computer –> Files上传下载好的 .mp3 音乐 –> 点进上传好的音乐 –> 复制URLs
添加 Gitalk 评论
新建Github仓库
https://github.com/new
新建一个仓库用来存储评论,评论将会存储仓库 Issue 中
注册GitHub OAuth应用
https://github.com/settings/applications/new
Application name: Gitalk
Homepage URL: http://blog.zoiii.cn
Authorization callback URL: http://blog.zoiii.cn
Enable Device Flow
Register application
获取Client ID 和 Client Secret
修改配置
themes/next/_config.yml 修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| gitalk: enable: true github_id: zoiiiiii # GitHub 仓库所有者 repo: gitalk # 用于存储 issues 的仓库名称 client_id: # 获取的Client ID client_secret: # 获取的Client Secret admin_user: zoiiiiii # GitHub 仓库所有者和协作者,只有这些人可以初始化 GitHub issues distraction_free_mode: true # 类似 Facebook 的无干扰模式 # 当官方代理不可用时,可以更改为自己的代理地址 proxy: https://cors-anywhere.azm.workers.dev/https://github.com/login/oauth/access_token # 这是官方代理地址 # Gitalk 的显示语言取决于用户的浏览器或系统环境 # 如果希望访问您网站的所有人都看到统一的语言,可以设置强制语言值 # 可选值: en | es-ES | fr | ru | zh-CN | zh-TW language: en
|
添加黑白模式切换
根目录
1
| npm install hexo-next-darkmode --save
|
themes/next/_config.yml 添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| # Darkmode JS # For more information: https://github.com/rqh656418510/hexo-next-darkmode, https://github.com/sandoche/Darkmode.js darkmode_js: enable: true bottom: '16px' # default: '32px' right: '96px' # default: '32px' left: 'unset' # default: 'unset' time: '0.5s' # default: '0.3s' mixColor: 'transparent' # default: '#fff' backgroundColor: 'transparent' # default: '#fff' buttonColorDark: '#121212' # default: '#100f2c' buttonColorLight: '#121212' # default: '#fff' isActivated: false # default false saveInCookies: false # default: true label: ◑ # default: '' autoMatchOsTheme: false # default: true libUrl: # Set custom library cdn url for Darkmode.js
|
SEO 优化
生成 sitemap.xml
1
| npm install hexo-generator-sitemap --save
|
生成 RSS
1
| npm install hexo-generator-feed --save
|
自动推送至搜索引擎
1
| npm install hexo-seo-autopush --save
|
自定义
themes/next/source/css/_schemes/Gemini/index.styl 最下面添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| // 自定义样式
.site-title { font-size: 15px !important; }
// .main-menu { // font-size: 14px; // }
.main-inner { font-size: 14px; }
.fa-tags { font-size: 15px; }
.live2d-widget-container { z-index: 999 !important; }
body .darkmode-toggle { width: 26px !important; height: 26px !important; border-radius: 0 !important; opacity: 0.8; color: #fff; font-size: 16px; z-index: 999 !important; }
@media (max-width: 576px) { .aplayer { display: none !important; } .darkmode-toggle { bottom: 24px !important; right: 16px !important; }
.sidebar-toggle { right: 16px; left: auto; } }
@media (min-width: 577px) and (max-width: 991px) { .aplayer { display: block !important; } .sidebar-toggle { right: 96px; left: auto; } .darkmode-toggle { bottom: 24px !important; right: 96px !important; } }
// 平板以下样式 @media (max-width: 768px) { .darkmode-toggle { width: 26px !important; } }
@media (min-width: 1200px) { .main { width: 1120px; } }
@media (max-width: 1201px) { .main { width: 1180px; } }
|
themes/next/layout/_macro/sidebar.njk
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| {% macro render(display_toc) %} <aside class="sidebar"> {%- if display_toc %} {%- set toc = toc(page.content, {class: 'nav', list_number: page.toc.number, max_depth: page.toc.max_depth}) %} {%- set display_toc = toc.length > 1 and display_toc %} {%- endif %}
<div class="sidebar-inner {% if display_toc %}sidebar-nav-active sidebar-toc-active{% else %}sidebar-overview-active{% endif %}"> <ul class="sidebar-nav"> <li class="sidebar-nav-toc"> {{ __('sidebar.toc') }} </li> <li class="sidebar-nav-overview"> {{ __('sidebar.overview') }} </li> </ul>
<div class="sidebar-panel-container"> <!--noindex--> <div class="post-toc-wrap sidebar-panel"> {%- if display_toc %} <div class="post-toc animated">{{ toc }}</div> {%- endif %} </div> <!--/noindex-->
<div class="site-overview-wrap sidebar-panel"> {{ partial('_partials/sidebar/site-overview.njk', {}, {cache: theme.cache.enable}) }}
{{- next_inject('sidebar') }}
{# 移动到这里 #} {%- if theme.links %} <div class="links-of-blogroll animated"> <div class="links-of-blogroll-title"> {%- if theme.links_settings.icon %}<i class="{{ theme.links_settings.icon }} fa-fw"></i>{% endif %} {{ __('sidebar.links') }} </div> <ul class="links-of-blogroll-list"> {%- for blogrollText, blogrollURL in theme.links %} <li class="links-of-blogroll-item"> {{ next_url(blogrollURL, blogrollText, {title: blogrollURL}) }} </li> {%- endfor %} </ul> </div> {%- endif %} </div> </div>
{%- if theme.back2top.enable and theme.back2top.sidebar %} <div class="back-to-top animated" role="button" aria-label="{{ __('accessibility.back_to_top') }}"> <i class="fa fa-arrow-up"></i> <span>0%</span> </div> {%- endif %} </div>
{# 移动到上面 #} {# {%- if theme.links %} <div class="sidebar-inner sidebar-blogroll"> <div class="links-of-blogroll animated"> <div class="links-of-blogroll-title"> {%- if theme.links_settings.icon %}<i class="{{ theme.links_settings.icon }} fa-fw"></i>{% endif %} {{ __('sidebar.links') }} </div> <ul class="links-of-blogroll-list"> {%- for blogrollText, blogrollURL in theme.links %} <li class="links-of-blogroll-item"> {{ next_url(blogrollURL, blogrollText, {title: blogrollURL}) }} </li> {%- endfor %} </ul> </div> </div> {%- endif %} #}
{%- if theme.related_posts.enable %} {%- if theme.pjax %} <div class="pjax"> {%- endif %} {%- if page.related_posts and page.related_posts.length > 0 %} <div class="sidebar-inner sidebar-post-related"> <div class="animated"> {{ partial('_partials/post/post-related.njk') }} </div> </div> {%- endif %} {%- if theme.pjax %} </div> {%- endif %} {%- endif %} </aside> {% endmacro %}
|