Back

Somnia 主题架构概述

Without further ado
| markdown

提醒:本文档为 AI 生成,如需使用请自行验证其内容。

Somnia 是一个基于 Hugo 的主题,适用于内容型网站(博客、文档、个人主页)。
在保持 SEO 友好的同时借助 Swup.js 提供接近 SPA 的流畅体验。

技术栈:Hugo + Alpine.js + UnoCSS + Swup.js + Medium Zoom

设计定位

适合内容型网站或轻量级 Web 应用,在以下两个目标之间取得平衡:

  • SEO 友好 — Hugo 服务端渲染输出完整 HTML,搜索引擎可直接索引
  • SPA 体验 — Swup.js 拦截页面间导航,AJAX 加载内容,无刷新过渡

目录


技术架构总览

用户请求 ─→ Hugo(SSG)─→ 静态 HTML ─→ 浏览器
                    Swup.js 拦截同站导航 ←→ AJAX 加载新页面
                Alpine.js 重新初始化组件
                Async Alpine 按需加载第三方库
text
层次技术定位
生成Hugo v0.158.0+扩展版,服务端渲染
样式UnoCSS 66.x原子化 CSS,4 个预设
交互Alpine.js 3.14+声明式 DOM 绑定,15 个指令
懒加载Async Alpine代码分割,按需加载组件
导航Swup.js无刷新页面过渡
滚动Swup Scroll Plugin切换时保存/恢复滚动位置
预加载Swup Preload Plugin悬停链接时预加载资源
图片缩放Medium Zoom点击放大预览

主题自定义机制

Hugo 查找优先级:website > theme

website/assets/js/custom.js     ← 优先使用
website/themes/Somnia/assets/js/custom.js  ← 仅当前者不存在时
text

核心原则:website/ 下创建与主题同路径的文件即可覆盖,无需修改主题源码。
覆盖的文件不会随主题更新而变化,升级时需手动 diff 合并。


Hugo 模板体系

布局文件结构

关键模板说明

  • baseof.html — 定义 --highlightColor CSS 变量,#content-wrapper 为 Swup 切换容器
  • head/theme.html — 内联脚本,DOM 渲染前从 localStorage 读取主题,防闪烁
  • data.html — 通过 data-somnia 属性触发 KaTeX 等第三方库按需加载

JavaScript 架构

文件组织

加载顺序

  1. head/theme.html 内联脚本初始化主题色(防闪烁)
  2. head/js.html 按顺序加载:
    • variable.js → 定义全局变量(如 SOMNIA_LIBSBASE_URL
    • main.js → 实例化 Somnia 类,定义工具方法和第三方库管理器
    • components.js → 通过 alpine:init 注册 Alpine 组件和全局 Store
    • custom.js → 用户覆盖的 welcome 信息、CDN 路径、初始化钩子
    • Swup.js + 插件 → 初始化无刷新导航,绑定 #content-wrapper
    • Alpine.js → 扫描 DOM 中的 x-data 指令,初始化组件

模块职责

文件职责
variable.js存储全局变量、配置参数,在各模块间共享
main.js主入口,初始化全局 Somnia 实例,提供 showToastloadResourcetimestampToShichenscanLine 等工具方法
components.jsAlpine.store('somnia')(主题/暗色状态)、10 个组件函数:headerComponentmainComponentbackToTopComponentquoteComponentheroComponenttocComponentsomniaDatasearchComponent
custom.js用户自定义逻辑,可覆盖 PageInitCustom()swupPageInitCustom() 钩子

第三方库管理

Somnia.prototype.libs 实现了一套通用的库加载/运行接口,每个库有 loaded()ok()load()run() 四个方法:

加载方式触发条件
Medium Zoom全局打包始终可用,Swup 切换后自动重新绑定
Pagefind按需 CSS + JS搜索页面 searchComponent() 加载
KaTeX按需 CSS + JS文章 Front Matter 设 math: true

Swup.js 与 Alpine.js 的协作

  • Swup 拦截链接点击 → AJAX 获取新页面 → 替换 #content-wrapper → 触发页面切换事件
  • Alpine.js 自动检测新 DOM 中的 x-data 指令并初始化
  • 组件开发关键: Swup 切换后 <script> 标签不会自动执行,因此 shortcode 中的 x-data="fn()" 需要额外处理。详见组件编写指南

CSS 样式体系

文件组织

UnoCSS 体系

Somnia 使用 UnoCSS 作为原子化 CSS 引擎,通过 uno.config.ts 配置:

  • presetMini — 基础预设(必需)
  • presetAttributify — 属性化模式:<div p-4> 替代传统 class
  • presetTypography — 排版预设:自定义 prose 类,覆盖标题锚点、引用块、表格、列表、内联代码等
  • themeColors — CSS 变量映射到工具类:text-primarybg-mutedborder-border

开发时需同时运行 UnoCSS 监听进程:

pnpm unocss "layouts/**/*.html" -o ./assets/css/uno.css --watch
bash

CSS 变量主题色

所有颜色通过 CSS 变量在 :root.dark 中定义,通过 UnoCSS 的 themeColors 映射到工具类:

变量用途对应类
--primary主色调(高亮色)text-primarybg-primary
--foreground / --background文字/背景text-foregroundbg-background
--muted / --muted-foreground柔和色bg-mutedtext-muted-foreground
--border / --input / --ring边框/输入框/焦点环border-border
--radius圆角rounded-*
--highlightColor渐变高亮色内联 style

加载方式

通过 head/css.html 用 Hugo Pipes 加载:

{{ $css := resources.Get "css/main.css" | fingerprint }}
<link rel="stylesheet" href="{{ $css.RelPermalink }}">
html

注意: CSS @import 语法需要 Hugo >= v0.158.0 支持。


短代码组件

Somnia 内置了 22 个短代码,分为四类:

类别短代码说明
基础cardcalloutlabelquotetoast卡片、提示框(4 种风格)、标签、引用、消息
布局tabscollapsetimelinesteps标签页、折叠面板、时间线、步骤指示器
增强qrcodelink-previewgithub-cardbilibiliformatted-date二维码、链接预览、GitHub 卡片、B站嵌入、日期
工具card-listmd2htmlscriptdate列表容器、Markdown 转 HTML、脚本嵌入

完整用法和参数说明见组件文档


配置参数

站点 hugo.toml[params] 下可配置:

参数路径说明
params.limit分页:blogPosts/blogCategories/blogTags 等
params.author名称、邮箱、头像、GitHub、简介
params.homepage首页文章数、一言开关
params.header.menu导航栏菜单项列表
params.footer页脚:ICP 备案、版权信息
params.features功能开关(search 等)
params.comment评论系统(provider: Artalk / Mastodon)
params.education / params.certifications首页教育/证书区块
params.websites首页友情网站列表
params.skills首页技能标签

完整配置示例见 exampleSite/config/_default/hugo.toml


补充说明

版本要求

  • Hugo extended,最低 v0.158.0(CSS @import 支持)
  • pnpm v10+(UnoCSS 构建)
  • Node.js 20+(推荐)
  • Pagefind(可选,搜索索引)

相关文档

Docs