静态资源
DIY 站点,从静态资源开始定制
本 CMS 的静态资源均位于 public/ 下。本节介绍其目录结构,以及可直接使用和需要替换的资源。
静态资源结构
目录树public/
├── emojis/ 评论表情
├── fonts/ 字体
├── icons/ 文章正文用的技术图标
├── imgs/ 图片
├── skills/ 关于页的技能图标
├── favicon.ico
├── manifest.webmanifest
└── robots.txtCDN 解析机制
本项目支持将静态资源托管于 CDN 上,节省主站带宽并可配置缓存。
本章节只介绍在不配置 CDN 时如何自定义静态资源。配置 CDN 的文档请参照 CDN 配置 文档,除了上云需做额外处理,其他都跟本章节一致。
不配置 CDN 时,这些静态资源和 Nuxt 打包的 CSS 和 JS 都走站点自己的域名。配置 CDN 时,在 site.config.ts 里填上 _cdnUrl 之后,生产环境会把它们换成 CDN 域名下的地址,本地开发不受影响。
emojis
emojis 目前有三组表情,分别是 Heo 表情、猫猫虫和猫咪,用在评论区的表情面板,服务端渲染邮件时也用同一份映射。
图片按组放在 public/emojis/ 下,映射表是 app/assets/emojis.json,顶层 key 对应一组表情的目录,每条形如:
JSON"Heo-Sticker": {
"heo-3d眼镜": "/emojis/heo-sticker/3d眼镜.png"
}若要换成自己的表情,请把图片放进 public/emojis/ 下新建的目录,在 emojis.json 里加一层同名的顶层 key 和条目,再到 shared/emoji-categories.ts 的 EMOJI_CATEGORIES 里加一条:dataKey 跟 emojis.json 的顶层 key 对齐,prefix 既是 key 的前缀也是占位符的前缀。
例如,张洪 Heo 发布了 3D 版本的 Heo-Sticker 表情,个人博客可免费使用。下载并解压表情包后,在 public/emojis/ 下新建 heosticker3d 目录,再将表情图片放入其中。

修改 app/assets/emojis.json:
JSON{
"Heo-3D": {
"heo3d-爱心眼": "/emojis/heosticker3d/爱心眼.png",
"heo3d-安睡": "/emojis/heosticker3d/安睡.png",
"heo3d-傲娇": "/emojis/heosticker3d/傲娇.png",
"heo3d-抱心": "/emojis/heosticker3d/抱心.png",
"heo3d-抱熊": "/emojis/heosticker3d/抱熊.png"
}
}然后修改 shared/emoji-categories.ts 的 EMOJI_CATEGORIES 常量:
TypeScriptexport const EMOJI_CATEGORIES: EmojiCategoryMeta[] = [
{ dataKey: "Heo-Sticker", label: "Heo表情", prefix: "heo-" },
{ dataKey: "capoo", label: "猫猫虫", prefix: "猫猫虫-" },
{ dataKey: "Cat", label: "猫咪", prefix: "cat-" },
{ dataKey: "Heo-3D", label: "Heo表情3D", prefix: "heo3d-" },
];结果:

emojis 位于 public/ 文件夹下,因此可以部署到 CDN。public/ 内的所有资源均无需手动处理 CDN 接入逻辑,是否配置 CDN 都由 ImQi1 CMS 自动适配。
其实我有想过统一,因为它确实是设计上的缺陷,但是面对我想要的门槛还是妥协了。在快速开始里面其实我就说了,我想提高这个项目被人使用的门槛,所以很多地方我都没有复用或采用自动扫描,而是分散在项目中,包括这处。同时,我认为这样可以加快你对此项目的理解,比如你按照上述步骤成功新增了你喜欢的自定义表情,那你就相当于探索了一部分的 public、shared,而它们只是你全面认识此项目的开始。
能随身所欲 DIY 此项目的前提就是你要对本项目的每一处代码都要了解。基于我写的代码,你能 DIY 出具有你自己理解和审美的网站,才是我想看到的。
fonts
public/fonts/font.css 里有两部分。正文是 Noto Serif SC,101 个 @font-face 按 unicode-range 分片;代码是 JetBrainsMono,分 ASCII、Symbols、Rest 三片,取自 JetBrainsMono Nerd Font。ASCII 那片在 src 里先找本机装的同名字体,找不到才回落到打包的 woff2,Symbols 与 Rest 两片则直接用打包的 woff2,其中 Symbols 覆盖箭头、货币和数学、技术符号。
两个字体变量在 app/assets/css/main.css 里,--font-serif 给正文,--font-mono 给代码。font.css 本身是在 nuxt.config.ts 的 app.head 里引入的。
以把代码字体换成 0xProtoNerdFontMono 为例(附 Nerd 字体下载地址:https://www.nerdfonts.com/font-downloads ):
删除 JetBrains Mono 的三个字体,把 0xProtoNerdFontMono 放进 public/fonts/:

建议使用 woff2 字体。与 ttf 相比,woff2 占用空间更小,现代浏览器也普遍支持。本例为便于演示使用 ttf。
然后在 public/fonts/font.css 中删除 JetBrainsMono 的三段定义,替换为以下定义:
CSS@font-face {
font-display: swap;
font-family: "0xProtoNerdFontMono";
font-style: normal;
font-weight: 400;
src: url(0xProtoNerdFontMono-Regular.ttf) format("truetype");
}再改 app/assets/css/main.css 里的字体变量:
CSS --font-mono: "JetBrainsMono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji";
--font-mono: "0xProtoNerdFontMono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji"; 结果:

icons
public/icons/ 下 24 个 SVG 分两种用途。16 个给代码块用,代码块带了文件名时按扩展名取图标,没有扩展名就按语言,挂在左上角文件名前面,映射在 app/composables/useMarkdownContent.ts 的 iconMap 里。另外 8 个是正文链接的品牌图标,Github、Gitee、百度、Google、腾讯、微信、Mozilla 和 npm,在 app/components/markdown/MarkdownBody.vue 里按 .markdown-link-icon--名字 这个类名做 mask 渲染。
imgs
imgs 文件夹存放多类图片资源,具体用途如下:
| 文件名 | 引用方 | 用途 |
|---|---|---|
program.webp / game.webp / music.webp / photo.webp / reading.webp / travel.webp | app/pages/about.vue | 关于页 - 兴趣爱好六个翻转卡片配图(编程 / 游戏 / 音乐 / 摄影 / 阅读 / 旅行) |
jixi.webp / ysu.webp / shenyang.webp | app/pages/about.vue | 关于页 - 「游山玩水」三张城市 / 校园配图(鸡西 / 燕山大学 / 沈阳) |
enfj.svg | app/pages/about.vue | 关于页 - MBTI 主人公 ENFJ 头像 |
shenyang.webp | app/pages/index.vue | 首页 - 主题切换预览的「layout」主题配图(与 about 共用同一文件) |
links-cover.png | app/pages/links.vue | 友链页 - 页顶封面图 |
message-cover.png / nopic.png | app/pages/messages.vue | 留言页 - 页顶封面图 + 无头像 / 无封面占位图 |
avatar.webp | site.config.ts (site.avatarPath) | 全站默认头像 |
imqi1.svg | site.config.ts (seo.ogImage) + public/manifest.webmanifest | 站点 logo(OG 图、PWA 图标通用矢量图) |
miniprogram.jpg | site.config.ts (pages.homeLinks[].qrcode) | 联系方式 - 微信小程序二维码 |
foreverblog.png / travelling.png / boyouquan.png / blogfinder.png / storeweb.png | site.config.ts (pages.links.blogOrganizations) | 友链 - 五个友链站点图标(十年之约 / 开往 / 博友圈 / Blogfinder / 个站商店) |
imqi1-144.png | nuxt.config.ts (apple-touch-icon) | Apple Touch Icon 180×180 |
frontend-screenshot1.png / frontend-screenshot2.png | public/manifest.webmanifest | PWA 应用截图(桌面 1280×720 / 移动 510×820) |
其他文件(夹)
skills 图标仅用于关于页面的【技能 / 技术栈】模块。
favicon.ico 是浏览器标签页标题左侧的小图标,请替换为自己的图标,并保持文件名一致。
manifest.webmanifest 是 PWA 所需的清单,将在 PWA 章节中详细介绍修改方法。
robots.txt 规定搜索引擎爬虫抓取站点时应遵守的协议,请将其中的域名替换为站点自身域名。