vite-plugin-assets-manager
v0.0.3
Published
A Vite plugin for managing image assets via a virtual module
Maintainers
Readme
vite-plugin-assets-manager
一个 Vite 插件,通过虚拟模块 virtual:assets 管理图片资源,并在构建时支持压缩、打包 ZIP、上传。
1. 当前实现能力
- 开发环境:
virtual:assets导出本地路径(以/开头) - 生产构建:
virtual:assets导出 CDN URL(固定规则:defaultDomain/activity/cdnPrefix/文件名) - 支持具名导出和默认导出对象
- 自动扫描图片目录并生成导出名(驼峰)
- 导出名冲突自动处理并告警
- 构建前读取 Git 变更文件(已暂存 + 未暂存 + 未跟踪)
- 构建时压缩图片并打包为单个 ZIP 上传
- 上传结果输出彩色日志与表格
- 在缓存目录生成 HTML 预览报告
- 开发环境监听图片变更并触发全量刷新
2. 安装与使用
npm i -D vite-plugin-assets-manager// vite.config.ts
import vitePluginAssets from 'vite-plugin-assets-manager'
export default {
plugins: [
vitePluginAssets({
defaultDomain: 'https://cdn.example.com',
}),
],
}// 任意业务代码
import { logo } from 'virtual:assets'
import assets from 'virtual:assets'
console.log(logo)
console.log(assets.logo)3. 配置参数(完整)
vitePluginAssets(options) 的参数定义来源于 src/index.ts 与 types/index.d.ts。
| 参数 | 类型 | 必填 | 默认值 | 用途 |
|---|---|---|---|---|
| defaultDomain | string | 是 | - | 生产构建时 CDN 域名前缀 |
| cdnPrefix | string | 否 | vite 项目根目录名 | CDN 路径前缀 |
| imageDir | string[] | 否 | ['src/assets'] | 扫描/监听/过滤图片目录 |
| extensions | string[] | 否 | ['png','jpg','jpeg','gif','webp','svg','avif'] | 允许处理的扩展名(不含点) |
| compressOptions | CompressOptions | 否 | 见下表 | 构建压缩参数 |
| uploadOptions | UploadOptions | 否 | - | 构建上传参数;未配置 uploadUrl 时不做压缩/上传 |
| cleanCache | boolean | 否 | true | 构建开始时是否清理缓存目录 |
CompressOptions:
| 参数 | 类型 | 默认值 | 用途 |
|---|---|---|---|
| quality | number | 80 | JPEG/WebP/AVIF 质量 |
| progressive | boolean | true | JPEG 渐进式 |
| mozjpeg | boolean | true | JPEG 使用 mozjpeg |
UploadOptions:
| 参数 | 类型 | 默认值 | 用途 |
|---|---|---|---|
| uploadUrl | string | - | 上传接口地址 |
| skipUpload | boolean | false | 跳过真实上传 |
| headers | Record<string,string> | {} | 自定义请求头 |
4. 虚拟模块行为
4.1 导出名规则
由 src/scan.ts 的 pathToExportName() 处理:
- 去扩展名
- 按
/和-拆分 - 组装为驼峰
示例:
logo.png->logoicons/arrow-up.svg->iconsArrowUpbackgrounds/dark-mode.svg->backgroundsDarkMode
如果导出名冲突,scanImages() 会追加父目录前缀并打印警告。
4.2 开发环境导出
由 src/virtual.ts 的 generateDevCode() 生成:
- 具名导出值:
/相对项目根目录路径 - 默认导出:所有资源键值对象
示例:
export const viteLogo = '/src/assets/vite-logo.svg'*
export default { viteLogo: '/src/assets/vite-logo.svg' }4.3 生产构建导出
由 src/virtual.ts 的 generateProdCode() 生成:
*
- URL 规则:
defaultDomain + '/activity/' + cdnPrefix + '/' + 文件名 - 仅使用文件名(
path.basename),不保留原始子目录
示例:
export const iconsArrowUp = 'https://cdn.example.com/activity/playground/arrow-up.svg'5. 构建时压缩与上传流程
实现位于 src/index.ts、src/git.ts、src/compress.ts、src/upload.ts。
buildStart触发(仅当配置了uploadOptions.uploadUrl)getModifiedFiles(root)读取 Git 变更(三类,均排除已删除文件):git diff --cached --name-only --diff-filter=ACMRT(已暂存未提交)git diff --name-only --diff-filter=ACMRT(未暂存的修改)git ls-files --others --exclude-standard --full-name(未跟踪的新文件)
filterModifiedImages()过滤出:- 位于
imageDir - 扩展名在
extensions - 文件实际存在(已删除文件会跳过)
- 位于
compressImages()压缩到缓存目录zipImages()打包为${cdnPrefix}.zipuploadZipFile()上传 ZIP,并打印成功/失败表格- 若存在失败文件,抛错中断构建
5.1 上传请求格式
当前 ZIP 上传实际发送字段(见 src/upload.ts):
- Method:
POST - Body:
multipart/form-data - Field:
files(ZIP 文件) - Headers:
uploadOptions.headers
5.2 上传响应处理
uploadZipFile() 期望响应里有 data.urls: string[],通过 URL 文件名判断成功项。
特殊处理:
- 若
message包含file exists,按警告处理并继续,不抛错
5.3 压缩策略
compressImage() 按扩展名处理:
jpg/jpeg: JPEG 压缩png: PNG 压缩webp: WebP 压缩avif: AVIF 压缩svg/gif: 直接复制- 其他格式:直接复制
6. Vite Hook 与方法用途
对应 src/index.ts:
| Hook/方法 | 用途 |
|---|---|
| configResolved | 保存 resolvedConfig,确定 cdnPrefix |
| buildStart | 构建前执行变更扫描、压缩、打包、上传 |
| buildEnd | 当前不做清理(保留最新缓存) |
| resolveId | 处理 virtual:assets;并拦截 imageDir 里的图片直接导入 |
| load | 生成虚拟模块代码;处理拦截资源为 export default "" |
| configureServer | 监听图片目录变更,更新类型并触发 full-reload |
7. 缓存与产物
缓存目录:node_modules/vite-plugin-assets-manager/.cache
- 构建开始时:若
cleanCache=true,先清理旧缓存 - 构建结束后:保留缓存
- 上传阶段会生成
vite-plugin-assets-preview-时间戳.html
8. TypeScript 类型
类型入口:
在业务项目中加入:
/// <reference types="vite/client" />
/// <reference types="vite-plugin-assets/types/virtual-assets" />说明:插件运行时会写入插件包的 types/virtual-assets.d.ts(见 src/types.ts)。
9. 已知实现细节
- 生产 URL 使用文件名,不保留目录层级
- ZIP 打包使用文件名作为条目名,不保留目录层级
- 同名文件来自不同目录时,可能发生覆盖风险
resolveId对扩展名匹配大小写敏感(id.endsWith('.ext'))
10. 测试
可用脚本(见 package.json):
npm run build
npm run test
npm run test:upload
npm run test:build测试文档见 test/README.md,示例项目见 playground/README.md。
