博客的相册功能做了一次优化,现在只需要把照片放到指定文件夹,页面就会自动显示,不用再手动配置每张照片的路径了。
原来的问题
之前的相册功能需要在 YAML 配置文件中手动填写每张照片的路径:

- id: "travel-2023"
title: "旅行 2023"
cover: "/img/cover/3.webp"
photos:
- "/img/gallery/travel-2023/1.jpg"
- "/img/gallery/travel-2023/2.jpg"
- "/img/gallery/travel-2023/3.jpg"
# 每加一张照片都要手动添加...
这种方式有几个明显的痛点:
| 问题 | 描述 |
|---|---|
| 繁琐 | 每张照片都要手动写路径 |
| 易错 | 文件名写错就显示不出来 |
| 不直观 | 想加照片还得打开配置文件 |
我想要的效果很简单:把照片丢进文件夹,刷新页面就能看到。
解决方案
实现一个自动扫描功能,在构建时读取文件夹中的所有图片。
文件夹结构
public/img/gallery/
├── travel-2023/ # 相册文件夹(文件夹名 = 相册ID)
│ ├── 01.jpg
│ ├── 02.jpg
│ └── 03.webp
├── daily/
│ ├── photo1.png
│ └── photo2.webp
└── ...

核心代码
创建一个扫描函数,读取指定文件夹中的所有图片:
import fs from 'node:fs';
import path from 'node:path';
const GALLERY_DIR = 'public/img/gallery';
const IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.webp', '.gif', '.avif'];
export function scanAlbumPhotos(albumId: string): Photo[] {
const albumPath = path.join(process.cwd(), GALLERY_DIR, albumId);
if (!fs.existsSync(albumPath)) {
return [];
}
const files = fs.readdirSync(albumPath);
const photos: Photo[] = [];
for (const file of files) {
const ext = path.extname(file).toLowerCase();
if (IMAGE_EXTENSIONS.includes(ext)) {
photos.push({
id: path.basename(file, ext),
url: `/img/gallery/${albumId}/${file}`,
filename: file,
});
}
}
// 按文件名排序
return photos.sort((a, b) =>
a.filename.localeCompare(b.filename, undefined, { numeric: true })
);
}
自动发现相册
不仅照片可以自动扫描,相册本身也可以自动发现:
export function scanAllAlbums(): Album[] {
const galleryPath = path.join(process.cwd(), GALLERY_DIR);
if (!fs.existsSync(galleryPath)) {
fs.mkdirSync(galleryPath, { recursive: true });
return [];
}
const entries = fs.readdirSync(galleryPath, { withFileTypes: true });
const albums: Album[] = [];
for (const entry of entries) {
if (entry.isDirectory()) {
const albumId = entry.name;
const photos = scanAlbumPhotos(albumId);
if (photos.length > 0) {
albums.push({
id: albumId,
title: albumId, // 默认用文件夹名作为标题
cover: photos[0].url, // 第一张图作为封面
photos,
});
}
}
}
return albums;
}
可选的 YAML 配置
如果想自定义相册标题和描述,仍然可以在 YAML 中配置:
- id: "travel-2023" # 对应文件夹名
title: "旅行 2023" # 自定义标题
description: "探索世界的足迹"
代码会自动合并扫描结果和配置信息,配置优先级更高。
最终效果
现在的使用流程变得非常简单:

使用步骤:
- 在
public/img/gallery/下创建文件夹 - 把照片放进去
- 重启开发服务器或重新构建
- 完成!
支持的图片格式:jpg、jpeg、png、webp、gif、avif
自动处理:
- 照片按文件名排序(支持数字排序,如 1, 2, 10 而不是 1, 10, 2)
- 第一张照片自动作为相册封面
- 自动统计照片数量
小技巧
照片排序
如果想控制照片的显示顺序,可以用数字前缀命名:
01-风景.jpg
02-人物.jpg
03-美食.jpg
自定义封面
如果不想用第一张照片作为封面,可以在 YAML 中指定:
- id: "travel-2023"
cover: "/img/cover/custom-cover.webp" # 自定义封面
隐藏相册
如果某个文件夹不想显示为相册,可以用下划线开头命名:
public/img/gallery/
├── travel-2023/ # 会显示
├── _drafts/ # 不会显示(以下划线开头)
写在最后
这个优化虽然不大,但确实让日常使用方便了很多。
以前想加几张照片,还得打开编辑器、找到配置文件、手动添加路径。现在直接把照片拖进文件夹就完事了,符合直觉,零学习成本。
好的工具应该是无感的——你不需要思考怎么用,自然而然就会用。这次优化就是朝着这个方向迈进了一小步。