技术文章/工程化
用 Vite 插件解决一个真实的构建产物问题
故事的起点很简单:我们的构建产物需要输出到带版本号的目录,而打包完成后还得手动改一次 HTML 里的引用路径。
先想清楚它在哪个阶段发生
Vite 插件的钩子很多,常见误区是把事情放在 buildEnd 里做——那时候文件已经写完了,你再改就得自己处理文件 IO。正确的位置是 generateBundle:文件已在内存里,但还没落盘。
import type { Plugin } from 'vite'
export function versionedAssets(version: string): Plugin {
return {
name: 'wwcong:versioned-assets',
enforce: 'post',
generateBundle(_options, bundle) {
for (const [fileName, chunk] of Object.entries(bundle)) {
if (chunk.type === 'asset' && fileName.endsWith('.html')) {
chunk.source = String(chunk.source).replace(
/(src|href)="\/(_nuxt|assets)\//g,
`$1="/v${version}/$2/`,
)
}
}
},
}
}
代码不多,但有三个细节值得说:
enforce: 'post'保证它在其他插件的转换之后运行,看到的 HTML 是最终形态。- 直接改
chunk.source,不写文件——交给 Vite 统一落盘。 - 版本号从参数传入而不是插件内部读取,这样它就是个纯函数,测试的时候不用 mock 环境变量。
结果
原本每次发布要手动执行的 3 步操作,变成了构建配置里的一行:
plugins: [versionedAssets(pkg.version)]
判断一件事值不值得自动化,我的标准是:它每个月重复超过 5 次,而且每次都能精确描述步骤。 这个改动花了 40 分钟,之后每次发布省 2 分钟,两个月就回本了。
评论
还没有评论,坐个沙发?