You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在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)),
        },
    },
});

插件说明

  1. generateBundle钩子:在Rollup完成打包、准备输出文件时触发,此时可以访问所有即将输出的chunk和资源文件。
  2. 修改资源引用:遍历所有资源文件,获取其内置的hash值,然后替换所有chunk和HTML中对应的资源路径,添加?v=[hash]查询参数。
  3. 输出文件名:保持entryFileNames、chunkFileNames、assetFileNames为不带哈希的格式,确保文件能正常生成。

这样构建后,实际输出的文件是不带哈希的(如assets/someCss.css),但页面中引用的URL会变成assets/someCss.css?v=82315f25,同样能实现缓存击穿的效果。

内容的提问来源于stack exchange,提问作者Arno van Oordt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 20:22:53