Vite 0.1.7:构建追踪与资源映射新升级

版本:0.1.7 | 协议:MIT | 依赖:Vite >=5.0.0 <8.0.0


写在前面

v0.1.7 的主题是:让构建产物可追踪,让资源映射可编程

在 SPA/MPA 应用中,构建产物经过 hash 命名后,原始文件名与实际输出路径之间的映射关系难以获取。v0.1.7 新增的 assetManifest

插件,在构建完成后自动扫描输出目录,生成资源映射清单(manifest.json),支持 Vite 标准、Webpack 兼容和自定义三种输出格式,并可按入口分组或将清单注入为运行时全局变量,实现从构建到运行时的完整资源追踪链路。

本版重点

能力 一句话说明 你需要做什么
assetManifest 资源清单生成 构建后自动生成资源映射清单,支持三种格式、入口分组和运行时注入 新增配置
assetManifest 按入口分组 将资源按入口点分类,区分 JS/CSS/其他文件 新增配置
assetManifest 运行时注入 将清单以全局变量注入 HTML,运行时可直接访问资源映射 新增配置

升级方式 :修改 devDependencies 中版本号为 ^0.1.7。无 Breaking Changes,完全向后兼容。


一、5 分钟快速上手

1.1 安装与最小配置

json 复制代码
{
	"devDependencies": {
		"@meng-xi/vite-plugin": "^0.1.7"
	}
}
typescript 复制代码
import { assetManifest } from '@meng-xi/vite-plugin'

export default defineConfig({
	plugins: [assetManifest()]
})

1.2 立刻看到效果

构建完成后,dist/manifest.json 自动生成:

json 复制代码
{
	"version": "1.0",
	"timestamp": "2026-06-07T15:30:00.000Z",
	"publicPath": "/",
	"assets": {
		"index.html": "/index.html",
		"assets/index-abc123.js": "/assets/index-abc123.js",
		"assets/index-def456.css": "/assets/index-def456.css",
		"assets/logo-ghi789.png": "/assets/logo-ghi789.png"
	}
}

1.3 运行时访问清单

启用 injectRuntime 后,在浏览器中可直接访问资源映射:

typescript 复制代码
// vite.config.ts
assetManifest({
	injectRuntime: true,
	runtimeGlobalName: '__ASSET_MANIFEST__'
})

// 运行时代码
const manifest = window.__ASSET_MANIFEST__
console.log(manifest.assets['assets/logo-ghi789.png']) // '/assets/logo-ghi789.png'

二、核心能力:assetManifest 资源清单生成

2.1 三种输出格式

Vite 标准格式(默认)

键为原始资源路径,值为带 publicPath 的输出路径,并包含版本号和时间戳元信息:

json 复制代码
{
	"version": "1.0",
	"timestamp": "2026-06-07T15:30:00.000Z",
	"publicPath": "/",
	"assets": {
		"index.html": "/index.html",
		"assets/index-abc123.js": "/assets/index-abc123.js"
	}
}
Webpack 兼容格式

模拟 Webpack ManifestPlugin 的输出结构,包含 entriesassets 两个字段,方便从 Webpack 迁移的项目使用:

json 复制代码
{
	"entries": [
		{
			"name": "main",
			"files": ["/assets/index-abc123.js", "/assets/index-def456.css"]
		}
	],
	"assets": {
		"index.html": "/index.html",
		"assets/index-abc123.js": "/assets/index-abc123.js"
	}
}
自定义格式

通过 customFormatter 回调函数,完全控制输出结构:

typescript 复制代码
assetManifest({
	outputFormat: 'custom',
	customFormatter: assets => {
		// 只输出 JS 和 CSS 文件
		const filtered = Object.fromEntries(Object.entries(assets).filter(([key]) => key.endsWith('.js') || key.endsWith('.css')))
		return { files: filtered, generatedAt: new Date().toISOString() }
	}
})

2.2 按入口分组

启用 groupByEntry 后,清单中会包含按入口点分组的资源信息,将每个入口关联的 JS、CSS 和其他资源文件分类整理:

typescript 复制代码
assetManifest({
	outputFormat: 'vite',
	groupByEntry: true
})

生成的清单会额外包含 groups 字段:

json 复制代码
{
	"version": "1.0",
	"timestamp": "2026-06-07T15:30:00.000Z",
	"publicPath": "/",
	"assets": { "...": "..." },
	"groups": [
		{
			"entry": "main",
			"assets": {
				"js": ["/assets/index-abc123.js"],
				"css": ["/assets/index-def456.css"],
				"other": ["/assets/logo-ghi789.png"]
			}
		},
		{
			"entry": "vendor",
			"assets": {
				"js": ["/assets/vendor-xyz999.js"],
				"css": [],
				"other": []
			}
		}
	]
}

2.3 运行时注入

启用 injectRuntime 后,插件会在构建完成后将资源映射表以 <script> 标签的形式注入到输出目录中的所有 HTML 文件的 </head> 标签前:

typescript 复制代码
assetManifest({
	injectRuntime: true,
	runtimeGlobalName: '__ASSET_MANIFEST__'
})

注入后的 HTML:

html 复制代码
<head>
	<script>
		window.__ASSET_MANIFEST__ = { assets: { 'index.html': '/index.html', 'assets/index-abc123.js': '/assets/index-abc123.js' } }
	</script>
	<!-- 其他 head 内容 -->
</head>

运行时即可通过全局变量访问:

typescript 复制代码
const manifest = window.__ASSET_MANIFEST__
const jsFiles = Object.keys(manifest.assets).filter(key => key.endsWith('.js'))

2.4 文件过滤

通过 includeExtensionsexcludeExtensionsexcludePaths 灵活控制清单包含的文件:

typescript 复制代码
assetManifest({
	// 只包含 JS 和 CSS 文件
	includeExtensions: ['.js', '.css'],

	// 排除 source map 和压缩文件(默认行为)
	excludeExtensions: ['.map', '.gz', '.br'],

	// 排除特定路径
	excludePaths: ['assets/icons/', 'assets/sprites/']
})

优先级excludePaths > excludeExtensions > includeExtensions

2.5 公共路径前缀

publicPath 会自动添加到所有资源路径前,适配 CDN 部署场景:

typescript 复制代码
assetManifest({
	publicPath: 'https://cdn.example.com/'
})

输出结果:

json 复制代码
{
	"assets": {
		"assets/index-abc123.js": "https://cdn.example.com/assets/index-abc123.js"
	}
}

2.6 实例方法

插件实例提供三个方法供外部访问清单数据:

typescript 复制代码
const plugin = assetManifest({ outputFormat: 'vite', groupByEntry: true })

// 构建完成后...
const assetMap = plugin.pluginInstance?.getAssetMap?.() // 资源映射表
const manifest = plugin.pluginInstance?.getManifest?.() // 完整清单数据
const groups = plugin.pluginInstance?.getGroups?.() // 入口分组信息

2.7 冲突检测

构建资源映射表时,如果出现原始路径冲突(多个文件映射到同一个输出路径),插件会自动输出警告日志,帮助发现潜在的构建配置问题。


三、配置选项

选项 类型 默认值 描述
outputFormat 'vite' | 'webpack' | 'custom' 'vite' 清单输出格式
outputFile string 'manifest.json' 清单输出文件名,相对于构建输出目录
includeExtensions string[] [] 包含的文件扩展名,为空则包含所有
publicPath string '/' 公共路径前缀
injectRuntime boolean false 是否将清单注入为运行时全局变量
runtimeGlobalName string '__ASSET_MANIFEST__' 运行时全局变量名称
customFormatter CustomFormatter | null null 自定义格式化器,仅 custom 格式时生效
groupByEntry boolean false 是否按入口分组资源
excludeExtensions string[] ['.map', '.gz', '.br'] 排除的文件扩展名
excludePaths string[] [] 排除的路径模式列表

继承 BasePluginOptions 通用配置:enabledverboseerrorStrategy


四、类型导出

类型 描述
AssetManifestOptions 插件配置选项
ManifestOutputFormat 清单输出格式类型
AssetMap 资源映射表,键为原始路径,值为输出路径
AssetGroup 按入口分组的资源信息
AssetManifestResult Vite 格式的完整清单数据
WebpackEntryAsset Webpack 格式的入口资源信息
WebpackManifestOutput Webpack 格式的完整清单输出
CustomFormatter 自定义格式化器函数类型

五、实战场景

5.1 CDN 预加载

typescript 复制代码
import { defineConfig } from 'vite'
import { assetManifest } from '@meng-xi/vite-plugin'

export default defineConfig({
	plugins: [
		assetManifest({
			outputFormat: 'vite',
			publicPath: 'https://cdn.example.com/',
			injectRuntime: true,
			runtimeGlobalName: '__ASSET_MANIFEST__'
		})
	]
})

运行时根据清单预加载关键资源:

typescript 复制代码
const manifest = window.__ASSET_MANIFEST__
Object.values(manifest.assets)
	.filter(path => path.endsWith('.js'))
	.forEach(path => {
		const link = document.createElement('link')
		link.rel = 'prefetch'
		link.href = path
		document.head.appendChild(link)
	})

5.2 SSR 资源映射

typescript 复制代码
import { assetManifest } from '@meng-xi/vite-plugin'

export default defineConfig({
	plugins: [
		assetManifest({
			outputFormat: 'vite',
			groupByEntry: true
		})
	]
})

SSR 服务端读取清单文件,根据入口名获取对应的 JS/CSS 文件路径:

typescript 复制代码
import manifest from './dist/manifest.json'

function getEntryAssets(entryName: string) {
	const group = manifest.groups?.find(g => g.entry === entryName)
	return {
		scripts: group?.assets.js ?? [],
		styles: group?.assets.css ?? []
	}
}

5.3 Webpack 迁移兼容

typescript 复制代码
import { assetManifest } from '@meng-xi/vite-plugin'

export default defineConfig({
	plugins: [
		assetManifest({
			outputFormat: 'webpack'
		})
	]
})

生成的清单与 Webpack ManifestPlugin 格式兼容,无需修改下游消费代码。

5.4 uni-app 项目

typescript 复制代码
import { assetManifest } from './uni_modules/vite-plugin/js_sdk/index.mjs'

export default defineConfig({
	plugins: [
		uni(),
		assetManifest({
			outputFormat: 'vite',
			outputFile: 'manifest.json',
			injectRuntime: true,
			groupByEntry: true,
			enabled: process.env.NODE_ENV === 'production'
		})
	]
})

六、子路径导出变更

子路径 变更 内容
@meng-xi/vite-plugin/plugins/asset-manifest 新增 assetManifest 函数及所有类型导出

七、迁移指南

从 v0.1.6 升级到 v0.1.7

1. 启用资源清单生成(可选)
typescript 复制代码
import { assetManifest } from '@meng-xi/vite-plugin'

export default defineConfig({
	plugins: [assetManifest()]
})
2. 按需配置高级功能
typescript 复制代码
assetManifest({
	outputFormat: 'vite', // 或 'webpack'、'custom'
	publicPath: '/', // CDN 场景设为 CDN 域名
	injectRuntime: true, // 运行时访问清单
	groupByEntry: true, // 按入口分组
	excludeExtensions: ['.map', '.gz', '.br'] // 排除不需要的文件
})
3. 子路径独立导入
typescript 复制代码
import { assetManifest } from '@meng-xi/vite-plugin/plugins/asset-manifest'
import type { AssetManifestOptions, AssetMap } from '@meng-xi/vite-plugin/plugins/asset-manifest'

本文基于 @meng-xi/vite-plugin@0.1.7 版本撰写,所有代码示例均来自实际源码。

相关推荐
qq4356947012 小时前
Vue02
开发语言·前端·javascript
AsiaLYF2 小时前
Kotlin MutableSharedFlow: emit vs tryEmit 详解
开发语言·前端·kotlin
喜欢踢足球的老罗2 小时前
Chrome MV3 插件架构深度解析:Service Worker 生命周期与 Token 管理的三层博弈
前端·chrome·架构
小李云雾2 小时前
Pinia:Vue3 全局状态管理从入门到精通
前端·javascript·vue.js
Upsy-Daisy2 小时前
Hermes Agent 学习笔记 03:CLI 与 TUI 使用体验,让 Agent 真正进入终端工作流
服务器·前端·数据库
KaMeidebaby2 小时前
卡梅德生物技术快报|噬菌体筛选:技术实操:宽谱大肠杆菌噬菌体筛选全流程与性能验证方案
前端·人工智能·算法·数据挖掘·数据分析
风吹夏回2 小时前
Vue3 + Element Plus 完整使用指南
前端·javascript·vue.js·element
影寂ldy2 小时前
C# 泛型方法
java·前端·c#
依托偶尔宁2 小时前
element-plus:el-table设置展开图标所在列的位置
前端·elementui