惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Microsoft Azure Blog
Microsoft Azure Blog
MongoDB | Blog
MongoDB | Blog
小众软件
小众软件
Apple Machine Learning Research
Apple Machine Learning Research
O
OpenAI News
酷 壳 – CoolShell
酷 壳 – CoolShell
The GitHub Blog
The GitHub Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - 聂微东
Engineering at Meta
Engineering at Meta
W
WeLiveSecurity
Hacker News: Ask HN
Hacker News: Ask HN
大猫的无限游戏
大猫的无限游戏
Vercel News
Vercel News
D
Docker
F
Full Disclosure
AI
AI
罗磊的独立博客
博客园 - 【当耐特】
U
Unit 42
S
SegmentFault 最新的问题
Stack Overflow Blog
Stack Overflow Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
P
Palo Alto Networks Blog
博客园_首页
H
Help Net Security
量子位
月光博客
月光博客
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 司徒正美
F
Fortinet All Blogs
D
DataBreaches.Net
B
Blog RSS Feed
Webroot Blog
Webroot Blog
TaoSecurity Blog
TaoSecurity Blog
S
Secure Thoughts
爱范儿
爱范儿
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Attack and Defense Labs
Attack and Defense Labs
Application and Cybersecurity Blog
Application and Cybersecurity Blog
C
CERT Recently Published Vulnerability Notes
Martin Fowler
Martin Fowler
Blog — PlanetScale
Blog — PlanetScale
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
Securelist

青萍叙事

通过Hermes搭建AI驱动的全自动安全封禁系统 博客被攻击之后,我部署雷池防火墙给网站穿上防弹衣 个人博客第一次被攻击,评论区被植入恶意代码全记录 青萍AI图床:AI 生图接口文档 真心建议做一人企业的你,先把统一认证搞定 从个人公众号迁移到企业公众号经验总结 豆包千问集体下线智能体,是时候拥抱 Hermes Agent 了 配音兼职渠道怎么找?5 种渠道和 1 个避坑提醒 宝妈声音兼职去哪接单:三个平台横评,最后一个免费入驻每日自动派单 Hermes 浏览器工具:让 AI 替你操作网页 Hindsight for OpenCode:给每个项目装上专属记忆库 Hermes v0.17.0 最值得升级的理由:一个进程,管所有 Profile 音频可视化:从波形到视频的三种实现路径 Hermes 定时任务实战 真人配音兼职怎么找:几个渠道对比,末尾推荐一个免费入驻的 AI语音技术到底能做什么 AI漫剧之配音篇 用 Hermes Agent 搭了一条内容生产线 Hermes Gateway 飞书连接断开排查 2026精选5款热门AI配音软件 用 Hermes 打造 LLM Wiki 知识库:Karpathy 方法实战指南 用 Hermes 打造个人知识管理系统 给 Hermes 装上本地记忆:Hindsight 自部署完整记录 给 Hermes Agent 装上慧眼:GLM 视觉 MCP Server 配置指南 AI 配音多音字踩坑记 DeepSeek 5月六连崩,是时候重视 LLM API 故障转移了 做内容为什么最好用真人配音 青萍AI语音开放真人配音师入驻 给 Hermes 装上真记忆:Hindsight 上手指南 Hermes 多 Agent 管理指南 邀请有礼:把好用的 AI 工具分享出去,和朋友一起拿积分 Hermes Agent 基础配置指南:从零搭建你的 AI 管家 推荐一个免费在线音频编辑器,像剪映一样好用 我把小说变成了有声故事,而且每个人物都有自己的声音 FunASR 语音识别:让声音变成可编辑的文字 FFmpeg 音频格式转换实用指南 青萍AI语音多人对话模式:5分钟快速生成播客 青萍创作者平台伙伴共创计划正式启动 免费开源的 Screen Studio 平替!OpenScreen 让你的产品演示瞬间专业起来 语音合成入门:SSML 标记语言快速上手 还在为配音头疼?我宣布:这个免费工具彻底治愈了我 青萍AI语音:用 AI 重新定义你的声音 OpenClaw 记忆对比:向量化 VS Markdown,到底该怎么选?
建站一周年:从 NotionNext 迁移到 Hexo 安知鱼
青萍叙事 · 2026-04-06 · via 青萍叙事
心情随笔建站复盘思考

时间过得很快,从去年四月建站到现在,整整一年了。

这一年来,网站经历了从零搭建、持续日更、产品化探索等多个阶段。
但在一周年之际,我做了一个重要决定:从 NotionNext 迁移到 Hexo 安知鱼主题。

这篇文章,就是这次迁移的完整记录。

🧭 背景:为什么要迁移?

NotionNext 之痛

我最初选择 NotionNext 作为博客框架,核心原因是内容管理使用 Notion,写作体验非常好。
但使用一年下来,最大的痛点也逐渐暴露:

Notion 上游 API 频繁变更,导致经常无法构建发布。

对于一个博客来说,稳定是第一位的
你无法接受写了一篇文章,发布时发现构建失败了,而且你无法控制什么时候能修复——因为这取决于 Notion 的 API 变更和 NotionNext 项目的适配速度。

这种不确定性对于一个需要持续输出的博客来说是致命的。

为什么是 Hexo 安知鱼?

选定 Hexo + 安知鱼主题,主要有两个原因:

  1. Hexo 是老朋友。我很早以前就使用过 Hexo,对其工作机制非常熟悉,静态站点生成器的稳定性和可控性是动态依赖 Notion API 的方案无法比拟的。

  2. 安知鱼与 Heo 主题几乎一模一样。之前 NotionNext 使用的是 Heo 主题风格,安知鱼主题的设计风格与 Heo 几乎一致,这意味着我只需要少量的定制改造就能还原之前的视觉效果,迁移成本极低。

📦 从 Notion 迁移数据

迁移的第一步,是把 Notion 中的所有文章数据导出来。

1. 导出 Markdown

Notion 支持将页面导出为 Markdown 格式。但直接导出有几个问题:

  • 只导出了 Markdown,缺少封面图
  • 缺少 Hexo 需要的 front-matter 元数据
  • AI 摘要信息丢失,需从之前的缓存中读取

2. API 获取封面链接

Notion 导出的 Markdown 不包含封面图信息,需要通过 Notion API 补全:

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
import requests

NOTION_TOKEN = "your-integration-token"
DATABASE_ID = "your-database-id"

headers = {
"Authorization": f"Bearer {NOTION_TOKEN}",
"Notion-Version": "2022-06-28",
"Content-Type": "application/json",
}

response = requests.post(
f"https://api.notion.com/v1/databases/{DATABASE_ID}/query",
headers=headers,
json={"page_size": 100},
)

for page in response.json()["results"]:
cover = page.get("cover", {})
if cover.get("type") == "external":
cover_url = cover["external"]["url"]
elif cover.get("type") == "file":
cover_url = cover["file"]["url"]
print(f"Title: {page['properties']['title']['title'][0]['plain_text']}")
print(f"Cover: {cover_url}")

通过 API 遍历数据库中所有文章,提取封面链接并下载到自己的 青萍 AI 图床

3. front-matter 格式转换

NotionNext 的 front-matter 格式与 Hexo 不同,需要转换。核心字段映射如下:

NotionNext Hexo 说明
title title 文章标题
date date 发布日期
summary description 文章摘要
category categories 分类(Hexo 支持层级)
tags tags 标签
slug permalink URL 别名
cover cover 封面图

转换脚本会将每篇文章的 front-matter 从 NotionNext 格式转为 Hexo 格式,同时处理分类和标签的映射关系。

经过以上三个步骤,二百多篇文章就从 Notion 成功迁移到了 Hexo 的 source/_posts/ 目录。

🔧 Hexo 搭建与配置

数据准备好后,就是搭建 Hexo 站点和配置安知鱼主题。

1. 主题下载

1
2
3
4
5
6

hexo init blog
cd blog


git clone https://github.com/anzhiyu-c/hexo-theme-anzhiyu.git themes/anzhiyu

_config.yml 中启用主题:

1
theme: anzhiyu

2. 基础配置修改

安知鱼主题的配置项非常多,主要集中在 _config.anzhiyu.yml 中。

导航菜单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
menu:
首页: /
产品:
青萍AI图床: https://img.lusyoe.com || fa-solid fa-image
青萍AI视频: https://video.lusyoe.com || fa-solid fa-video
文章:
归档: /archives || anzhiyu-icon-box-archive
分类: /categories || anzhiyu-icon-shapes
标签: /tags || anzhiyu-icon-tags
友链:
友人帐: /links || anzhiyu-icon-link
朋友圈: /friends || anzhiyu-icon-artstation
留言板: /comments || anzhiyu-icon-envelope
我的:
音乐馆: /music || anzhiyu-icon-music
关于:
关于本人: /about || anzhiyu-icon-paper-plane
日常瞬间: /moments || anzhiyu-icon-bolt

分页配置

1
2
3
4
5
index_generator:
per_page: 12

archive_generator:
per_page: 36

页脚、站长信息

配置页脚的社交链接、版权信息、建站时间等,确保与旧站一致。

封面和字体

将全站字体和封面图替换为自己的 CDN 资源,提升加载速度。

3. 扩展页面

安知鱼主题支持多种扩展页面,我逐一搭建了以下页面:

  • links:友情链接页面,展示友链卡片
  • about:关于页面,包含个人信息、技能点、联系方式
  • moments:日常瞬间页面,类似朋友圈的短内容
  • friends:朋友圈页面,聚合友站最新动态
  • comments:留言板页面,接入 Twikoo 评论系统
  • music:音乐馆页面
  • categories:分类总览页面

每个页面都是独立的 Markdown 文件,放在 source/ 对应目录下。

4. 主题定制

安知鱼主题虽然开箱即用很棒,但要完美还原之前的 Heo 风格,还需要一些定制改造。

导航菜单改为垂直

安知鱼默认的导航菜单是水平排列的,让子菜单更多时比较难看,并且之前的 Heo 风格是垂直分组展示。
修改了 nav.pug 模板和 nav.styl 样式,将菜单改为垂直分组展示,每个一级菜单作为一个分组,二级菜单垂直排列。

右侧面板添加板块

在文章详情页的右侧面板中,增加了以下信息卡片:

  • 最新瞬间:展示最近的日常瞬间动态
  • 最近查看:展示最近更新的文章
  • 最新评论:接入 Twikoo 展示最新评论
  • 标签:展示标签云,方便快速导航

这些卡片通过修改 Pug 模板和 Stylus 样式实现,部分通过自定义 widget 组件完成。

站点统计添加 vercount

之前在 NotionNext 中就使用了自己部署的 vercount,迁移到 Hexo 后继续使用:

1
2
3
vercount:
enable: true
server: https://vercount.lusyoe.com

vercount 与不蒜子相比,数据更稳定,加载更快,而且支持自托管。

友链卡片定制

安知鱼默认的友链卡片样式比较简单。为了更好地展示友链信息,我新增了 flexcard-large 样式:

  • 更大的头像尺寸
  • 更清晰的信息层级
  • 更好的视觉效果

RSS 订阅是博客的基础功能,通过 hexo-generator-feed 插件实现:

1
2
3
4
5
feed:
enable: true
type: atom
path: rss/feed.xml
limit: 20

为保持兼容,修改 path

Algolia 搜索添加 slug 支持兼容

之前 NotionNext 使用 Algolia 搜索,文章 URL 格式为 /article/slug。迁移到 Hexo 后,需要确保搜索结果中的链接格式一致。

修改了搜索索引的生成逻辑,确保 slug 字段正确映射到 permalink,保持搜索结果的 URL 兼容性。

首页文章卡片添加简短摘要信息显示

安知鱼主题默认的首页文章卡片只显示标题、分类、标签和发布日期,缺少文章的摘要预览。

为了提升首页的信息密度,让访客快速了解每篇文章的内容,我对卡片布局进行了调整:

  • 将文章描述(description)内容显示在标题和标签之间。
  • 配置 index_post_content.method: 2,优先使用 front-matter 中的 description 字段,没有则自动截取正文
  • 标签和发布日期下移至卡片底部,与描述内容形成清晰的信息层级

文章详情页面左侧添加文章目录

安知鱼主题默认将文章目录(TOC)放在右侧面板中,但右侧面板已经包含了最新瞬间、最近查看、最新评论、标签云等多个信息卡片,信息密度非常高。
而且默认的 TOC 在滚动时会隐藏,实用性大打折扣,尤其是对于长篇技术文章。

为了提升阅读体验,我在文章详情页左侧新增了独立的 sticky 定位目录组件。

这样右侧面板专注于站点信息展示,左侧目录专注于文章导航,互不干扰。

5. URL 路径兼容

这是一个容易被忽视但非常重要的细节。

之前 NotionNext 的文章 URL 格式是 /article/slug,没有 .html 后缀也没有尾部斜杠。而 Hexo 默认生成的路径会在后面自动带上 .html/,比如 /article/slug.html/article/slug/

网站已经运营了一年,搜索引擎已经积累了大量的索引,如果 URL 格式变化会导致:

  • 搜索引擎收录的旧链接全部 404
  • 外部引用和友链失效
  • SEO 权重归零

解决方案分三步:

第一步,Hexo permalink 配置

_config.yml 中手动设置 permalink 格式,让生成的文件路径包含 .html

1
2
3
4
5
permalink: article/:slug.html
permalink_defaults: article/:slug.html
pretty_urls:
trailing_index: false
trailing_html: false

但 Hexo 默认的 :slug 是基于目录名 + 文章标题生成的,与我之前的 slug 格式不一致。
因此通过 Hexo 的 post_permalink 过滤器,从每篇文章的 front-matter 中读取自定义的 slug 字段来生成 permalink:

1
2
3
4
5
6
7
8
9
10
11
hexo.extend.filter.register("post_permalink", function (data) {
var raw = data.raw;
if (!raw) return data;
var fm = raw.match(/^---[\r\n]+([\s\S]*?)[\r\n]+---/);
if (!fm) return data;
var slugMatch = fm[1].match(/^slug:\s*(.+?)\s*$/m);
if (slugMatch && slugMatch[1]) {
data.__permalink = "article/" + slugMatch[1] + ".html";
}
return data;
}, 1);

这样 Hexo 生成的静态文件就会使用文章 front-matter 中指定的 slug,与旧站的 URL 路径完全一致。

第二步,Nginx try_files 配置

但还有一个问题:旧站的 URL 是 /article/slug(无 .html),而实际文件是 /article/slug.html。需要在 Nginx 层面做兼容,让无后缀的请求也能正确访问:

1
2
3
4
5
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri.html $uri/index.html =404;
}

关键在于 try_files 指令的 $uri.html——当请求 /article/slug 时,Nginx 会依次尝试:

  1. /article/slug(原路径,不存在)
  2. /article/slug.html(拼接 .html,命中!)
  3. /article/slug/index.html(目录下的 index)
  4. 返回 404

这样无论访问 /article/slug 还是 /article/slug.html 都能正常访问,完美保持了与旧站的 URL 兼容性。

6. 静态资源,全站 CDN 切换

最后一步是将所有静态资源切换到自己的 CDN,涵盖 CSS/JS 资源、字体文件、图片资源(favicon、logo 等)以及第三方库(Twikoo、vercount 等前端脚本)。

我编写了一个脚本,自动扫描主题配置中引用的所有远程 CDN 资源并批量下载到自己的 青萍 AI 图床,然后将主题配置中的 CDN 地址统一替换为 cdn.lusyoe.com

整个过程一键完成,无需手动逐个替换,大幅提升了资源加载速度。

🚀 部署

部署方案沿用了之前的 Docker + Nginx 方式:

1
2
3
4
5
6
7
8
9
10
11
FROM nginx:alpine

RUN rm -rf /usr/share/nginx/html/* && \
rm -rf /etc/nginx/conf.d/* && \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

COPY ./public/ /usr/share/nginx/html/
COPY ./nginx.conf /etc/nginx/nginx.conf

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

📊 迁移对比

对比项 NotionNext Hexo 安知鱼
内容管理 Notion Markdown 文件
构建稳定性 依赖 Notion API 本地构建,完全可控
主题风格 Heo 安知鱼(几乎一致)
部署方式 Docker + Nginx Docker + Nginx
搜索 Algolia Algolia(兼容)
评论 Twikoo Twikoo
计数 vercount vercount
CDN 阿里云 ESA 阿里云 ESA
写作体验 Notion 编辑器 Markdown 编辑器
构建速度 较慢(依赖 API) 秒级

💭 写在最后

建站一周年,从 NotionNext 迁移到 Hexo,这次迁移总共只花了 2天 时间,表面上看是技术栈的变更,但本质上是对稳定性的追求。

NotionNext 是一个非常优秀的项目,它让我快速搭建了博客,也让我体验到了 Notion 写作的便利。

但当博客发展到一定阶段,稳定可控方便快捷更重要。

迁移过程虽然有些繁琐,但结果令人满意。Hexo 的静态生成完全可控,不再受上游 API 变更的影响。

安知鱼主题的视觉效果与之前的 Heo 风格几乎一致,甚至略超一筹,迁移成本远低于预期。

如果你也在使用 NotionNext 并且遇到了类似的稳定性问题,或者正在考虑搭建博客,希望这篇文章能给你一些参考。