暂不支持移动端访问

图片、视频与文章资源处理

1634 字 8 分钟
AI 摘要

说明 AstroBlog 的文章图片解析、Astro 优化、R2 视频和文章列表瀑布流实现。

AstroBlog 中至少存在三类资源:src/ 下可以被 Astro 处理的本地图片,public/ 下按原路径输出的静态文件,以及远程 URL 或 R2 上的媒体。文章封面、正文插图和首页 Hero 视频的加载方式不同,不能用一个组件把它们全部当成普通字符串。

本地图片和远程图片#

src/utils/image-utils.tssrc/utils/local-image.ts 负责判断图片来源、解析本地资源和选择质量。src/components/common/CoverImage.astro 处理文章卡片与 Hero 封面;放在 src/ 的图片可以进入 Astro 的响应式优化,public/ 图片则直接由 URL 引用,不会被构建器转换。

文章正文的相对图片路径还需要知道文章文件所在目录。src/plugins/article-images/source-resolver.mjsindex.mjs 在 Markdown/MDX 处理阶段解析相对路径、图注、宽图和灯箱属性。这个步骤必须发生在正文渲染前,否则路径会相对于网站根目录解析,开发环境能显示、生产环境却 404。

正文图片和卡片封面不能共用裁剪规则。卡片可以使用固定比例来维持网格高度,正文图片必须保留原始比例,避免图表、代码截图和授权信息被裁掉。图片组件还要输出 alt、figcaption 和必要的授权信息。

首页视频和 R2#

首页 Hero 视频由 HomeVideoLayer.astro 负责渲染,生产媒体域名为 media.yukihime.dev。站点配置保存候选视频和当前选择,Layout.astro 只在首页添加 preconnect 和 DNS 预解析。视频节点带有候选数据属性,浏览器脚本根据设备和壁纸状态选择实际源。

视频不应该成为首页内容的唯一载体。标题、导航、文章入口和按钮都由 HTML 输出,视频加载失败时仍有完整的页面结构。百叶窗覆盖主视觉或用户关闭动态壁纸时,脚本会暂停视频;切换页面或替换视频节点时,需要清理旧的 play()loadeddata 和 visibility 监听。

文章列表瀑布流#

网格布局使用 PostPage.astro 的客户端脚本,而不是额外引入 Masonry 框架。脚本读取容器宽度、列数和卡片实际高度,将每张 .post-card-item 放入当前最短的列:

JavaScript
const itemWidth = (containerWidth - (colCount - 1) * gap) / colCount;
const colHeights = new Array(colCount).fill(0);
for (const item of items) {
// 每次放入当前最短列,避免普通 CSS Grid 留下纵向空洞。
const colIndex = colHeights.indexOf(Math.min(...colHeights));
const top = colHeights[colIndex];
item.style.position = "absolute";
item.style.width = `${itemWidth}px`;
item.style.top = `${top}px`;
item.style.left = `${colIndex * (itemWidth + gap)}px`;
// 记录该列下一张卡片可使用的顶部偏移。
colHeights[colIndex] += item.offsetHeight + gap;
}

实际代码还处理双侧栏时的列数、窄屏强制列表模式、图片加载后的重排、coverVisibilityChange、自定义布局切换事件和 astro:before-swap 清理。因为卡片高度依赖图片,初始化时必须等待未完成图片的 load 事件;否则容器高度会按占位高度计算,图片加载后卡片互相覆盖。

性能边界#

封面前两张使用 eager,其他文章使用 lazy;视频通过独立媒体域名和预连接减少握手时间;字体文件禁止内联进 CSS,避免 CJK 字体分片让首屏样式膨胀;生产构建使用 Terser、CSS 分割和资源压缩。图片质量由 siteConfig.imageOptimization 控制,当前格式为 WebP、质量 85。

性能优化还要检查移动端带宽、文章正文图片清晰度、视频暂停是否生效、瀑布流重排是否造成布局跳动,以及 Pagefind 是否仍然能从最终 HTML 读取文章正文。

资源修改入口#

修改文章图片解析:查 src/plugins/article-images/;修改封面显示:查 CoverImage.astroPostCard.astro;修改图片质量或格式:查 siteConfig.imageOptimizationimage-utils.ts;修改首页视频:查 HomeVideoLayer.astro、壁纸配置和 verify-home-wallpaper;修改瀑布流:查 PostPage.astro 的初始化、重排和清理函数。

Terminal windowpowershell
# 检查文章正文中的本地图片、远程图片和 figure 结构。
pnpm verify:article-images
# 验证首页视频候选、播放节点和壁纸模式。
pnpm verify:home-wallpaper
# 输出构建资源和关键 bundle 的性能审计结果。
pnpm audit:performance
# 在完整静态构建中确认图片、视频引用和 Pagefind 没有回归。
pnpm build

资源路径是构建契约的一部分。不要为了让本地图片显示而把路径硬编码成开发服务器地址,也不要在组件中绕过 Astro 的图片处理器直接读取源文件绝对路径。

正文图片插件的处理顺序#

文章图片插件先识别 Markdown/HTML 中的图片节点,再根据文章 entry 的源文件目录解析相对路径。解析成功后生成带尺寸、alt、图注和灯箱数据的 figure 结构;远程 URL 保留为外链,不尝试读取远程文件;路径不存在时应在构建阶段报告错误或保留可诊断的原始 URL,而不是静默替换成首页封面。

文章图片与封面图片使用不同的缓存和尺寸策略。封面通常需要固定宽度和响应式 srcset,正文图更关注原比例和长图加载。新增图片属性时要检查 Markdown transformer、ArticleContent.astro、灯箱脚本、Pagefind 忽略范围和无障碍 alt 文本。

瀑布流的布局时序#

瀑布流计算依赖三次状态:容器宽度确定、卡片 DOM 挂载、图片尺寸确定。PostPage.astro 先在页面切换后延迟初始化,再为未完成图片注册 load 监听;每次重排先清除旧的 inline position/width/top/left,再计算新列。修改卡片内部字体、摘要行数或封面比例,都可能改变高度,因此必须重新检查 resize 和 coverVisibilityChange。

资源目录和后台上传#

后台媒体管理区区分 public/assets/imagessrc/assets/images。前者适合需要稳定 URL 或由外部配置直接引用的文件,后者适合需要 Astro 优化的组件资源。上传时 MediaManager.svelte 和 GitHub Proxy 会限制目标目录与扩展名;移动文件后还要全局搜索旧 URL,避免内容 Frontmatter 继续引用已删除资源。

视频资源不应进入 Git 仓库的大型历史。生产 Hero 视频放在 R2/媒体域名,仓库只保存候选地址和播放策略。替换视频时检查 HTTP Range、Content-Type、移动端自动播放限制和 poster,否则桌面端正常不代表手机端能开始播放。

[ 公告 ]

如果你喜欢,那么欢迎来到我的世界!

了解更多
[ 音乐 ]
封面

音乐

找不到相关结果。
[ 目录 ]
[ 全部文章 ]