这个站的技术结构:分层、页面与部署
配置分三层
1 | _config.yml 站点:域名、链接格式、分页、部署 |
Hexo 的 alternate theme config 会把根目录的 _config.<主题名>.yml 深度合并进主题配置。三个名字必须一致:theme: chengic、themes/ 下的目录名、配置文件名。不同步不会报错,主题配置会静默回退到默认值。
站点与主题分离
| 内容 | 位置 |
|---|---|
| 文章、页面、图片 | source/ |
| 全站样式 | source/css/,一页一个文件 |
| 功能脚本 | source/js/,一个功能一个文件 |
| 主题模板 | themes/chengic/,尽量不动 |
换主题时站点层可以整体保留,这是分离的唯一目的。
页面类型
两类:source/_posts/*.md 按 permalink 生成文章页;source/<名字>/index.md 生成独立页面。
| 路径 | 实现 |
|---|---|
/archives/ |
主题模板 |
/tags/ |
ECharts 看板,stats.js 在浏览器端改配色 |
/music/ |
整页自绘 + 全局播放核心 |
/thread/ |
HTML 表格 + 筛选脚本 |
/macro/ |
表单 + 42 个模板 |
/nav/ |
手写 HTML + CSS 计数器 |
/site/time/ |
时间线标签 + timeline-archive.js 后处理 |
/links/ |
flink 模板 + 随机排序 |
/message/ |
Twikoo |
/about/ |
手写 HTML |
除评论和少量接口外,全部静态生成。
脚本分三层
- 引导层:
modules/shell.js、modules/settings.js - 功能层:音乐、日历、统计、阅读进度、鼠标、AI 面板
- 注入层:
inject/*.js,页面加载后执行一次,如 pjax 后重绑滚动、搜索懒加载
运行期插入的 <a> 不在 pjax 的拦截范围内,需要 pjax-relink.js 补绑,否则点击会整页跳转。
缓存
版本号写在引用处,改一次推一位:
1 | <link rel="stylesheet" href="/css/site-inject.css?v=20261103-revert1"> |
页面级资源写在 front-matter 或模板,全站注入写在 _config.chengic.yml 的 inject 段。
只改文件不推版本号,浏览器会继续用缓存。改 .pug 模板还需要重启 hexo server,否则 HTML 里仍是旧的内联样式。
部署
两条路径:GitHub Pages(github.lichengic.com,纯静态)与 Vercel(www.lichengic.com,带函数)。
1 | hexo g -d |
hexo-deployer-git 在 .deploy_git 提交一次,再推送到目标仓库。仓库里是 public/ 成品,源码留在本地。
这条路径的前提是托管平台能直接吃静态产物。如果平台的构建命令仍是 npm run build,而仓库里没有 package.json,构建会失败,站点停在最后一次成功的版本上。
容易出问题的地方
- 模板语法写进 JS 注释:
source/js/也会被当模板处理,注释里出现模板标记会导致构建失败。 - 样式被主题覆盖:主题
custom.css里同名规则带!important且加载在后,需要抬特异性或确认加载顺序。 - pjax 状态残留:全局监听要在
pjax:complete里先解绑再绑定。 - 音乐跨页中断:整页导航销毁
<audio>,需要用sessionStorage做续播快照。 - 构建成功但线上没更新:看
?v=、public/产物时间、平台是否真的重新构建,不能只看本地构建结果。



