跳转到内容

06 · 书签站点图标

导航页与管理端的书签卡片、中转站、预览区均使用同一套站点图标组件 BookmarkFavicon,不单独维护「管理端 Logo」资源。

目标实现
视觉统一同一 URL 在 nav / admin 显示相同域名 Logo
减少探测不再轮询 favicon.ico、第三方 icon 服务
控制配额构建期映射 + 浏览器缓存,避免重复无效请求
降级可读无 token 或加载失败时显示 Lucide Globe

图标尺寸:容器 size-10、圆角 rounded-[0.35rem],与 .bookmark-card 网格对齐。

db/data/bookmarks.ts
→ vpr generate:bookmark-logos(指纹未变则跳过)
→ bookmark-logos.json(URL → domain)
→ 运行时 logoDevImageUrl(domain) + PUBLIC_LOGO_DEV_TOKEN
→ <img src="https://img.logo.dev/…" />
  • 构建脚本不下载图片,只更新 JSON;图片仍由 Logo.dev CDN 在访问页面时提供。
  • 指纹:全部书签 URL 排序后的 SHA-256;bookmarks.ts 未变则整文件不重写。
  • 增量:仅新增或 URL 变更的条目写入;未变的 URL 复用已有 domain 映射。

管理端 保存 / 恢复 写回 bookmarks.ts 后会自动执行 generate-bookmark-logos(与 vpr build 前相同)。

说明
PUBLIC_LOGO_DEV_TOKENLogo.dev Dashboard 的 Publishable key(写入 .env,勿提交 Git)
.env.example变量名模板
GitHub ActionsSecret PUBLIC_LOGO_DEV_TOKEN(见 deploy.yml

本地示例:

Terminal window
PUBLIC_LOGO_DEV_TOKEN=pk_…

无 token 时 resolveBookmarkLogoImageUrl 返回 null,卡片显示 Globe 占位。

src/bookmarks/shared/lib/logo-dev.ts 中固定:

参数说明
size80与卡片逻辑尺寸匹配
formatwebp体积与透明度
retinatrue高分屏
fallbackmonogram无品牌图时用域名首字母

域名会去掉 www. 前缀再请求 API。

位置组件
书签卡片网格grid/BookmarkCardPreviewBookmarkFavicon
中转站列表项transfer/DragTransferStation
导航页卡片nav/.../NavBookmarkCard

编辑弹窗内单独上传图标;图标由书签 URL 推导,改链接后保存并重新生成映射即可。

Terminal window
vpr generate:bookmark-logos # 手动刷新 bookmark-logos.json
vpr build # 构建前会自动执行上述脚本

Logo.dev Community 档约 50 万次/月 CDN 请求;个人书签站通常足够。商业用途在生产环境需按 Logo.dev 归因要求 展示指向 Logo.dev 的可见链接。

路径职责
shared/components/BookmarkFavicon.tsx懒加载、失败降级
shared/lib/bookmark-logos.ts读 JSON、解析 URL
shared/lib/logo-dev.ts拼 Logo.dev 图片 URL
shared/data/bookmark-logos.json构建期生成(可提交)
scripts/generate-bookmark-logos.mjs指纹与增量逻辑

相关界面说明见 05 · 管理端编辑界面;部署见 07 · 持久化与部署