目标读者:完全没接触过前端/博客的”小白”。
跟着做,你会在 1~2 小时内拥有一个和本博客(Sky Blog)一样的、能在线访问的博客。
本教程所有命令在 Windows + Git Bash 下书写,macOS/Linux 用户只需把 git 换成同款命令即可。


目录


第 0 步:先搞懂 4 个概念

在动手之前,先花 5 分钟明白”我们到底在做什么”。用大白话解释:

概念 是什么 类比
静态博客 所有网页在本地提前做好(纯 HTML/CSS/JS),别人访问时直接”发卡片”给他 印刷好的传单,别人来拿现成的
Hexo 一个”工厂”:输入 Markdown 文章 → 输出一堆 HTML 网页文件 你写中文 → 机器帮你翻译成网页
GitHub Pages GitHub 提供的免费网页托管,绑定到你的仓库 免费租了一间房子放你的传单
Markdown 一种”加了记号”的纯文本,# 是标题、** 是加粗 记笔记时用 # 表示大标题

整体流程(全程就这一个循环):

写文章(.md)  →  hexo generate 生成网页(public/)  →  推送到 gh-pages 分支  →  访问 https://你的用户名.github.io/仓库名/

记住这条线,后面每一步都是围着它转的。


第 1 步:准备环境(15 分钟)

你需要 4 样东西,全部免费:

1.1 安装 Node.js(博客工厂的动力源)

  1. 打开 https://nodejs.org/zh-cn ,下载 LTS 版(如 20.x)
  2. 一路 Next 装完(默认即可)
  3. 验证是否装好(打开 Git Bash,输入):
node -v      # 应输出 v18 或更高,如 v20.11.0
npm -v # 应输出 10 或更高

1.2 安装 Git(版本管理 + 推送到 GitHub)

  1. 打开 https://git-scm.com/download/win 下载安装
  2. 安装向导里”默认选择”即可(建议:默认编辑器选 Notepad++ 或 VS Code)
  3. 安装后右键桌面,会出现 “Git Bash Here” —— 后面所有命令都在这个窗口敲
  4. 验证:
git --version     # 应输出 git version 2.x

1.3 注册 GitHub 账号

  1. 打开 https://github.com 注册(用户名决定你的博客地址)
  2. 登录后,新建一个空仓库:
    • 右上角 + → New repository
    • Repository name:myblog(随便起,英文小写)
    • 不要勾选 “Add a README file”
    • 点 Create repository

1.4 安装 VS Code(写文章用的编辑器)

  1. 打开 https://code.visualstudio.com 下载安装
  2. 装好后在任意文件夹右键 → “Open with Code”

✅ 环境就绪标志:node -v、git --version 都有输出,GitHub 账号能登录。


第 2 步:搭建 Hexo 骨架(10 分钟)

2.1 安装 Hexo 命令行工具

npm install -g hexo-cli
hexo -v # 能看到版本号即成功

2.2 创建博客项目

# 找一个你喜欢的目录(比如 D:\),进入后执行:
cd /d

# 用 hexo 初始化(myblog 是文件夹名,和仓库名一致)
hexo init myblog
cd myblog

# 安装依赖(把 package.json 里列的库都装好)
npm install

装完你会看到这样一个目录结构(先认识,不用背):

myblog/
├─ _config.yml # ★ 站点主配置(改这里)
├─ package.json # 依赖清单
├─ scaffolds/ # 模板(新文章会套用)
├─ source/ # ★ 你写的东西都在这里
│ ├─ _posts/ # 文章文件夹
│ └─ img/ # 图片资源
└─ themes/ # 主题文件夹
└─ landscape/ # 自带的默认主题(稍后换成 Sakura)

2.3 第一次预览

npx hexo server
# 浏览器打开 http://localhost:4000

能看到一个默认博客页面 = 骨架搭好了。按 Ctrl + C 停掉。

如果 hexo init 很慢或失败(网络问题),可以手动搭:

mkdir myblog && cd myblog
npm init -y
npm install hexo hexo-server hexo-renderer-marked hexo-renderer-ejs hexo-renderer-stylus hexo-renderer-pug hexo-generator-index hexo-generator-archive hexo-generator-tag hexo-generator-category hexo-generator-feed hexo-generator-search hexo-tag-bili hexo-tag-fancybox_img

然后自己建 source/_posts/、scaffolds/、themes/ 文件夹即可,效果一样。


第 3 步:安装 Sakura 主题

Sakura 是本博客使用的二次元主题(原作者 honjun,MIT 协议)。

3.1 下载主题到 themes 目录

cd myblog
git clone https://github.com/honjun/hexo-theme-sakura.git themes/sakura

3.2 启用主题

编辑 myblog/_config.yml,把 theme: 改成:

theme: sakura

3.3 认识”主题两套配置”(非常重要!)

Sakura 主题有两份配置文件,它们会自动合并:

文件 角色 什么时候改
themes/sakura/_config.yml 主题默认配置 极少改(它是模板)
_config.sakura.yml(自己建) 站点覆盖配置 ★ 日常改这里

⚠️ 大坑预告:两份配置的同名数组(比如 bg:、menus:)会拼接而不是覆盖!
例如两边都写 bg:,最终会得到 16 张背景图,前 8 张还可能是失效的。
规则:数组字段只在一处写(本项目统一写在 themes/sakura/_config.yml)。

新建 myblog/_config.sakura.yml,先放最小内容:

# 站点名与头像
siteName: 我的博客
favicon: /img/favicon.png
avatar: /img/favicon.png

第 4 步:站点配置 _config.yml

打开 myblog/_config.yml,重点改这几处:

4.1 站点信息

title: 我的技术博客          # 浏览器标签栏标题
subtitle: '记录技术与思考' # 副标题
description: '个人技术博客' # SEO 描述
author: Sky # 作者名
language: zh-CN # 语言
timezone: Asia/Shanghai # 时区

4.2 URL 和 root(★ 子目录部署的关键)

如果你要把博客放在 https://用户名.github.io/仓库名/(项目页),必须:

url: https://你的用户名.github.io/myblog
root: /myblog/ # ★ 末尾斜杠不能少

如果你要放在 https://用户名.github.io/(个人主页),改成:

url: https://你的用户名.github.io
root: /

root 决定所有资源路径的前缀。改错了,图片/样式全 404。

4.3 常用字段对照表

字段 作用
permalink 文章网址格式,如 :year/:month/:day/:title/
theme 主题名(第 3 步已改)
deploy 部署配置(见第 9 步,建议留空不用)
index_generator.per_page 首页每页文章数

第 5 步:主题配置 _config.sakura.yml

把 _config.sakura.yml 补全(这是”主题如何设置”的核心):

5.1 菜单

menus:
首页: { path: /, fa: fa-home }
归档: { path: /archives/, fa: fa-archive }
标签: { path: /tags/, fa: fa-tags }
分类: { path: /categories/, fa: fa-folder-open }
留言板: { path: /comment/, fa: fa-pencil-square-o }
友人帐: { path: /links/, fa: fa-link }
关于: { path: /about/, fa: fa-heart }

fa: 是 Font Awesome 图标名,想换图标去 https://fontawesome.com/v4/icons/ 查。

5.2 头像与 favicon

favicon: /img/favicon.png
avatar: /img/favicon.png

把你的头像图片放到 source/img/favicon.png(没有 img 文件夹就新建)。

5.3 壁纸(首页背景图)

做法一(推荐,本项目采用):直接改 themes/sakura/_config.yml:

bg:
- /img/wallpaper/1.webp
- /img/wallpaper/2.webp
- /img/wallpaper/3.webp
# ...想加几张加几行
bgclass: "" # 空=原图 filter-dim=加阴影 filter-grid=横条纹 filter-dot=点点

把图片放到 source/img/wallpaper/ 下(建议 .webp 格式,体积小加载快)。

⚠️ 绝不要同时在 _config.sakura.yml 里再写 bg: —— 会变成 16 张图(数组拼接的坑)。

5.4 背景音乐(APlayer)

aplayer:
id: 19723756 # 网易云歌单 ID(这个是"飙升榜")
server: netease
type: playlist
fixed: true # 固定显示在左下角
autoplay: false # 不要自动播放(浏览器会拦)
loop: all
order: random
preload: auto
volume: 0.7

想换歌单:打开网易云音乐网页版 → 找到一个歌单 → 网址里 /playlist?id=xxxxxx 的 xxxxxx 就是 ID。

⚠️ 网易云外链大量失效,播放器会”卡在”放不了的歌上。
本项目已把播放器改成坏链自动跳下一首(改的是 themes/sakura/layout/_partial/aplayer.ejs)。
想要最稳:把自己 mp3 放进 source/music/,改成本地播放列表。

5.5 社交链接

# PC 端(左下角)
social:
github: { url: https://github.com/你的用户名, img: /img/social/github.png }
email: { url: mailto:you@example.com, img: /img/social/email.svg }

# 移动端(汉堡菜单里)
msocial:
github: { url: https://github.com/你的用户名, fa: fa-github, color: 333 }
email: { url: mailto:you@example.com, fa: fa-envelope, color: dd4b39 }

social 的 img: 需要准备图标图片放进 source/img/social/;msocial 用字体图标不需要图片,更省事。

5.6 首页 START:DASH 三张卡片

startdash:
- {url: /about/, title: 关于, desc: 了解本站, img: /img/wallpaper/1.webp}
- {url: /archives/, title: 归档, desc: 全部文章, img: /img/wallpaper/2.webp}
- {url: /tags/, title: 标签, desc: 按标签浏览, img: /img/wallpaper/3.webp}

第 6 步:写第一篇文章

6.1 创建

cd myblog
npx hexo new "我的第一篇博客"

生成的文件:source/_posts/我的第一篇博客.md。用 VS Code 打开,front-matter(--- 之间的部分)写成:

---
title: 我的第一篇博客
date: 2026-08-27 18:00:00
updated: 2026-08-27 18:00:00
tags:
- 生活
categories:
- 生活
photos:
- /img/cover/cover1.jpg
---

--- 下面就是正文,用 Markdown 语法写:

# 一级标题
## 二级标题

**加粗**、*斜体*、`行内代码`

- 列表项 1
- 列表项 2

正文里需要代码块时,单独用三个反引号包裹即可(不要和上面的示例嵌套):

console.log("代码块");

6.2 Front-matter 字段速查

--- 之间的内容叫 front-matter(文章”身份证”):

字段 必填 说明 示例
title ✅ 标题 title: 我的博客
date ✅ 发布时间 date: 2026-08-27 18:00:00
updated – 更新时间 updated: 2026-08-28 09:00:00
tags – 标签(可多个) tags: [技术, github]
categories – 分类(可多个) categories: [技术]
photos – 封面图(数组,第一张是封面) photos: [/img/cover/a.jpg]
description – 列表页摘要 description: 一句话介绍
mathjax – 数学公式 mathjax: true

6.3 封面图怎么设置?(重点)

Sakura 主题的封面字段是 photos 数组(不是 cover!用 cover 不生效):

photos:
- /img/cover/my-cover.jpg

步骤:

  1. 建目录 source/img/cover/,把图放进去
  2. front-matter 写 photos: [/img/cover/my-cover.jpg]
  3. 重新生成 → 文章页顶部就有封面大图,列表页缩略图也用它

以 / 开头的路径 = “资源根”,Hexo 会自动加上 root(如 /myblog/),最终访问
https://用户名.github.io/myblog/img/cover/my-cover.jpg。

6.4 正文里插图片

把图片放 source/img/post/,正文里写:

![图片说明](/img/post/xxx.png)

6.5 标签和分类有什么用

  • 标签:一篇文章可以贴多个,如”教程””Hexo””GitHub”
  • 分类:类似文件夹,一篇最好只归一个

它们会自动生成聚合页(如 /tags/GitHub/ 列出所有 GitHub 标签文章),
前提是你按第 7 步建了标签/分类根页。


第 7 步:搞定标签/分类页(新手必踩的坑)

症状:菜单点”标签”/“分类”,页面 404 或空白。

原因:Hexo 会自动生成”单个标签页”(/tags/GitHub/),
但不会自动生成”标签总览页”(/tags/)——除非你手动建了页面文件。

解决:在 source/ 下新建两个文件:

source/tags/index.md:

---
title: 标签
layout: tag # ★ 必须是单数 tag(不是 type: tags!)
description: 按标签浏览所有文章
---

source/categories/index.md:

---
title: 分类
layout: category # ★ 必须是单数 category
description: 按分类浏览所有文章
---

为什么不是 type: tags? Sakura 主题只提供了 tag.ejs(单数)这一个模板。
type: tags 会让 Hexo 去找 tags.ejs(复数),找不到就退回通用模板,
页面变成”空壳”。用 layout: tag 才能命中正确模板。

进一步美化(可选):Sakura 自带的 tag.ejs 在”总览页”上只显示最新文章,不显示标签列表。
本项目改成了”总览页显示全部标签+文章数”(themes/sakura/layout/tag.ejs 里判断
!page.tag 时渲染 site.tags 列表),单标签页行为不变。想抄的看本项目源码。


第 8 步:本地预览与排错

8.1 常用命令

npx hexo server        # 启动本地预览 http://localhost:4000
npx hexo generate # 生成静态文件到 public/
npx hexo clean # 清缓存(改配置不生效时用)

8.2 常见报错速查

报错 原因 解决
Port 4000 is already in use 端口被占 npx hexo server -p 4001
图片/样式 404 root 配置错 检查 _config.yml 的 root:
修改后页面没变 缓存 npx hexo clean && npx hexo generate
壁纸显示 CDN 默认图 数组 concat 见 §5.3,bg: 只写一处
标签页空白 没建 index.md 见第 7 步

第 9 步:部署上线到 GitHub Pages

这是最容易”翻车”的一步,按下面的推荐姿势做,稳。

9.1 把源码推到 GitHub

cd myblog

# 初始化 git(如果 hexo init 没自动做)
git init

# 关联你的远程仓库
git remote add origin https://github.com/你的用户名/myblog.git

# 第一次提交
git add .
git commit -m "init: hexo + sakura blog"
git push -u origin main

如果你仓库默认分支叫 master,就把 main 换成 master。
推送要账号密码/Token:GitHub 现在要求用 Personal Access Token(Settings → Developer settings → Personal access tokens),或先跑 gh auth login 登录 CLI。

9.2 在 GitHub 上启用 Pages

仓库页面 → Settings → Pages:

  • Source 选 Deploy from a branch
  • Branch 选 gh-pages,目录 / (root)
  • 点 Save

注意:这里选的是 gh-pages(产物分支),不是 main(源码分支)!

9.3 部署姿势一:独立目录法(★ 推荐,本项目用这个)

原理:把构建产物复制到一个独立的 git 仓库目录,只往 gh-pages 分支推。

# 1. 生成产物
cd myblog
npx hexo clean && npx hexo generate

# 2. 准备一个"独立部署目录"(第一次做)
mkdir /d/myblog_deploy
cd /d/myblog_deploy
git init
git remote add origin https://github.com/你的用户名/myblog.git
# 先随便提交一个空提交,让分支存在
git commit --allow-empty -m "init deploy branch"
git push -u origin HEAD:gh-pages

# 3. 每次发布:清空 → 复制 → 提交 → 推送
rm -rf /d/myblog_deploy/*
cp -r /c/你的路径/myblog/public/* /d/myblog_deploy/
touch /d/myblog_deploy/.nojekyll # ★ 必须有!见下方
cd /d/myblog_deploy
git add -A
git -c http.version=HTTP/1.1 commit -m "Site updated: $(date)"
git -c http.version=HTTP/1.1 push -f origin HEAD:gh-pages

为什么不能直接 npx hexo d?
当你把 myblog 文件夹本身变成 git 仓库后,hexo-deployer-git 的 .deploy_git
会”蹭用”根目录的 .git,结果 git add -A 把整个源码推上了 gh-pages,
GitHub Pages 找不到根 index.html → 404。这是本项目踩过的真事故,详见附录 B。

.nojekyll 是什么? 一个空文件,告诉 GitHub Pages”不要用 Jekyll 重新构建,
我给你的就是最终网页”。没有它,Jekyll 可能静默失败并沿用旧版,
表现为”明明推了新代码,线上还是老样子”。

9.4 部署姿势二:GitHub Actions 自动部署(推荐长期用)

见第 11 步,配一次之后每次 git push 就自动发布,本地不用装 Node。

9.5 首次访问

部署成功后等 1~2 分钟(GitHub Pages 构建需要时间),打开:

https://你的用户名.github.io/myblog/

看到自己的博客上线了 🎉 这就是全程的目标。


第 10 步:其他平台部署(Cloudflare / Vercel / Netlify)

这三个平台原理一样:连接你的 GitHub 仓库 → 填构建命令 → 平台帮你跑 → 发布。
共同配置:

配置项 值
构建命令(Build command) npm run build(package.json 里已定义 hexo generate)
输出目录(Output directory) public
Node 版本 20(在环境变量里设 NODE_VERSION=20)
环境变量 PUBLIC_URL=https://你的域名

注意:在这些平台部署时,_config.yml 的 url/root 要按平台给的域名改,
比如 Vercel 是 https://xxx.vercel.app,root 通常是 /。

10.1 Cloudflare Pages

  1. https://dash.cloudflare.com → Pages → Create a project → Connect to Git
  2. 选仓库 → Framework preset 选 Hexo
  3. 填上表的 Build command / Output directory
  4. Save and Deploy,等 1~2 分钟
  5. 自定义域名:项目 → Custom domains → 填域名,Cloudflare 自动配 CNAME + HTTPS

10.2 Vercel

  1. https://vercel.com → New Project → Import Git Repository → 选仓库
  2. Framework Preset 选 Other,Build Command 填 npm run build,Output 填 public
  3. Deploy,30 秒拿到 xxx.vercel.app
  4. 域名:Project → Settings → Domains

10.3 Netlify

  1. https://app.netlify.com → Add new site → Import an existing project → 选 GitHub 仓库
  2. Build command: npm run build;Publish directory: public
  3. Deploy site
  4. 域名:Site settings → Domain management → Add custom domain

第 11 步:GitHub Actions 自动部署

配好后,以后只做一件事:改完文章 git push,剩下全自动。

11.1 创建工作流文件

在 myblog/.github/workflows/deploy.yml 新建:

name: Deploy Hexo to gh-pages

on:
push:
branches: [main] # 推 main 时触发
workflow_dispatch: # 支持手动触发

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Build
run: npx hexo generate

- name: Deploy to gh-pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }} # 自动生成,无需手动配
publish_dir: ./public
publish_branch: gh-pages
force_orphan: true
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'

11.2 提交并验证

git add .github/workflows/deploy.yml
git commit -m "ci: 自动构建并发布到 gh-pages"
git push origin main

去仓库 Actions 标签页能看到工作流在跑。绿勾 = 成功,之后每次 push 都自动发布。


第 12 步:移动端适配

12.1 主题自带能力

Sakura 自带响应式:手机访问自动隐藏侧栏、汉堡菜单、压缩字体。一般不用动。

12.2 本项目做过的微调(可参考)

在 themes/sakura/source/css/style.css 追加:

/* 菜单强制一行,防止换行挤到第二行 */
.site-top .lower nav.navbar ul {
display: flex;
flex-wrap: nowrap;
white-space: nowrap;
}
.site-top .lower nav.navbar ul li {
float: none;
flex-shrink: 0;
white-space: nowrap;
margin: 0 15px; /* 间距调大,触屏更好点 */
}

12.3 测试不同设备

浏览器按 F12 → 左上角切换设备图标(Ctrl+Shift+M)→ 试 375px(iPhone SE)/ 768px(iPad)/ 1280px(桌面)。

优化建议:

  • 图片转 .webp(体积小一半)
  • 首页壁纸单张 ≤ 200KB
  • 文字大小在 @media (max-width: 768px) 里适当放大

第 13 步:日常维护(写文章、改壁纸、换封面)

13.1 发新文章的标准流程

cd myblog
npx hexo new "文章标题" # 1. 创建
# 2. VS Code 编辑 source/_posts/文章标题.md(写 front-matter + 正文)
npx hexo server # 3. 本地预览检查
npx hexo clean && npx hexo generate # 4. 重新生成
# 5. 推源码(GitHub Actions 会自动发布):
git add .
git commit -m "post: 文章标题"
git push origin main
# (若没配 Actions:走 §9.3 独立目录法推 gh-pages)

13.2 换壁纸

  1. 新图放 source/img/wallpaper/
  2. 改 themes/sakura/_config.yml 的 bg: 数组
  3. 重新生成 + 部署

13.3 换封面图

  1. 新图放 source/img/cover/
  2. 改文章 front-matter 的 photos:
  3. 重新生成 + 部署

13.4 备份

源码推到 main 就是最好的备份。定期:

git push origin main

附录 A:命令速查

用途 命令
装依赖 npm install
本地预览 npx hexo server
创建文章 npx hexo new "标题"
创建独立页 npx hexo new page 路径
生成静态文件 npx hexo generate(简写 hexo g)
清缓存 npx hexo clean
查看 git 状态 git status
提交 git add . && git commit -m "说明"
推源码 git push origin main
推产物(独立目录法) git -c http.version=HTTP/1.1 push -f origin HEAD:gh-pages
杀 node(Windows) PowerShell: Stop-Process -Name node -Force;CMD: taskkill /F /IM node.exe

附录 B:血泪避坑清单

🚨 1. 禁用 hexo d(本项目最大事故)

站点根目录本身是 git 仓库时,hexo deploy 会把整个源码 force push 到 gh-pages,
导致线上 404(找不到根 index.html)。
只用独立目录法(§9.3)或 GitHub Actions(§11)。

🚨 2. 主题配置数组是”拼接”不是”覆盖”

_config.sakura.yml 和 themes/sakura/_config.yml 的同名数组会 concat。
bg、menus、startdash 都中招。数组只写一处。

🚨 3. 子目录部署必须用 url_for()

主题里如果直接”字符串拼接”出路径(如 theme.cdn + '/img/xx'),子目录部署会 404。
Sakura 的 head.ejs(背景图)、startdash.ejs、headertop.ejs(头像)都踩过,
本项目已改为 url_for() 处理。改主题时遇到路径拼接,优先用 url_for()。

🚨 4. type: tags 会 404,要用 layout: tag

Sakura 只有 tag.ejs 单数模板。见第 7 步。

🚨 5. GitHub Pages 必须放 .nojekyll

否则 Jekyll 可能静默失败并沿用旧版。每次部署 touch .nojekyll。

🚨 6. 推送失败先试三板斧

git push origin main                              # ① 默认
git -c http.version=HTTP/1.1 push origin main # ② 解决 HTTP/2+代理 TLS 不兼容
env -u HTTP_PROXY -u HTTPS_PROXY git -c http.proxy= -c https.proxy= \
-c http.version=HTTP/1.1 push origin main # ③ 绕过代理直连

🚨 7. 网易云歌单外链大量失效

播放器会卡在放不了的歌。换歌单 ID 治标,本地 mp3 治本。


恭喜读到这里! 现在你已经能从零搭起并上线一个 Hexo + Sakura 博客了。
剩下就是多写、多改、多看 npx hexo server 的实时预览。
有问题就回看本教程的排错表,或者到 Hexo 文档 查。

赏