npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vite-plugin-assets-manager

v0.0.3

Published

A Vite plugin for managing image assets via a virtual module

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.tstypes/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.tspathToExportName() 处理:

  • 去扩展名
  • /- 拆分
  • 组装为驼峰

示例:

  • logo.png -> logo
  • icons/arrow-up.svg -> iconsArrowUp
  • backgrounds/dark-mode.svg -> backgroundsDarkMode

如果导出名冲突,scanImages() 会追加父目录前缀并打印警告。

4.2 开发环境导出

src/virtual.tsgenerateDevCode() 生成:

  • 具名导出值:/相对项目根目录路径
  • 默认导出:所有资源键值对象

示例:

export const viteLogo = '/src/assets/vite-logo.svg'*
export default { viteLogo: '/src/assets/vite-logo.svg' }

4.3 生产构建导出

src/virtual.tsgenerateProdCode() 生成: *

  • URL 规则:defaultDomain + '/activity/' + cdnPrefix + '/' + 文件名
  • 仅使用文件名(path.basename),不保留原始子目录

示例:

export const iconsArrowUp = 'https://cdn.example.com/activity/playground/arrow-up.svg'

5. 构建时压缩与上传流程

实现位于 src/index.tssrc/git.tssrc/compress.tssrc/upload.ts

  1. buildStart 触发(仅当配置了 uploadOptions.uploadUrl
  2. 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(未跟踪的新文件)
  3. filterModifiedImages() 过滤出:
    • 位于 imageDir
    • 扩展名在 extensions
    • 文件实际存在(已删除文件会跳过)
  4. compressImages() 压缩到缓存目录
  5. zipImages() 打包为 ${cdnPrefix}.zip
  6. uploadZipFile() 上传 ZIP,并打印成功/失败表格
  7. 若存在失败文件,抛错中断构建

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