能否在Vite中使用查询参数而非文件名哈希实现缓存击穿?
在Vite中使用查询参数实现缓存击穿的方案
直接修改assetFileNames为assets/[name].[ext]?v=[hash]会报错,原因是Rollup会把包含查询参数的字符串当作实际文件路径去创建文件,而文件系统不允许文件名中包含?符号,因此会出现找不到文件的错误。要实现用查询参数做缓存击穿,需要通过自定义插件修改资源引用的URL,而非直接修改输出文件名规则。
解决方法:自定义Vite/Rollup插件
通过插件在构建过程中修改资源的引用链接,给URL添加哈希查询参数,同时保持实际输出的文件名不带哈希。示例配置如下:
import { fileURLToPath } from 'node:url'; import { URL } from 'node:url'; import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; export default defineConfig({ plugins: [ vue(), { name: 'add-hash-query-param', apply: 'build', // 仅在构建阶段生效 generateBundle(options, bundle) { // 遍历所有输出的资源文件 for (const fileName in bundle) { const asset = bundle[fileName]; if (asset.type === 'asset') { // 获取资源的哈希值 const assetHash = asset.hash; // 修改所有chunk文件中的资源引用,添加查询参数 for (const chunkName in bundle) { const chunk = bundle[chunkName]; if (chunk.type === 'chunk') { chunk.code = chunk.code.replace( new RegExp(fileName, 'g'), `${fileName}?v=${assetHash}` ); } } // 修改HTML文件中的资源引用 if (bundle['index.html']) { bundle['index.html'].source = bundle['index.html'].source.replace( new RegExp(fileName, 'g'), `${fileName}?v=${assetHash}` ); } } } } } ], base: '/frontend', build: { outDir: '../www/public/frontend/', emptyOutDir: true, rollupOptions: { output: { // 输出不带哈希的文件名 entryFileNames: 'assets/[name].js', chunkFileNames: 'assets/[name].js', assetFileNames: 'assets/[name].[ext]', }, }, }, resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)), }, }, });
插件说明
generateBundle钩子:在Rollup完成打包、准备输出文件时触发,此时可以访问所有即将输出的chunk和资源文件。- 修改资源引用:遍历所有资源文件,获取其内置的
hash值,然后替换所有chunk和HTML中对应的资源路径,添加?v=[hash]查询参数。 - 输出文件名:保持
entryFileNames、chunkFileNames、assetFileNames为不带哈希的格式,确保文件能正常生成。
这样构建后,实际输出的文件是不带哈希的(如assets/someCss.css),但页面中引用的URL会变成assets/someCss.css?v=82315f25,同样能实现缓存击穿的效果。
内容的提问来源于stack exchange,提问作者Arno van Oordt
相关产品推荐
相关产品推荐

