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

如何配置Vite为XHR加载的静态资源添加哈希并获取文件名?

解决Vite中静态JSON文件的哈希缓存与XHR请求问题

针对你遇到的静态文件哈希与XHR加载的矛盾,这里提供三种可行方案,按推荐优先级排序:

方案一:用import.meta.glob让Vite自动追踪处理文件

这是最贴合Vite原生机制的方案,无需额外配置或插件:

  1. 保持src/assets/locales/目录结构不变
  2. 在代码中通过import.meta.glob批量导入语言文件,同时获取带哈希的文件URL:
// src/utils/locale-loader.js
// 批量导入文件内容(按需加载可去掉eager: true)
const localeContentMap = import.meta.glob('../assets/locales/*.json', { 
  eager: true, 
  import: 'default' 
});

// 批量获取带哈希的文件URL(用于XHR动态加载)
const localeUrlMap = import.meta.glob('../assets/locales/*.json', { 
  eager: true, 
  as: 'url' 
});

// 封装加载函数
export function loadLocale(lang) {
  // 直接获取已加载的内容(适合预加载场景)
  return localeContentMap[`../assets/locales/${lang}.json`];
  
  // 如果需要懒加载,用带哈希的URL发起XHR请求
  // return fetch(localeUrlMap[`../assets/locales/${lang}.json`])
  //   .then(res => res.json());
}
  1. 在业务代码中直接调用loadLocale('en')即可,Vite会自动将这些JSON文件打包到dist/assets并添加哈希后缀,localeUrlMap中存储的就是处理后的完整URL。

方案二:通过Rollup配置手动包含文件并生成清单

适合需要完全控制文件输出路径或批量处理大量静态文件的场景:

  1. 修改vite.config.js配置,让Rollup处理目标文件并生成资产清单:
// vite.config.js
import { defineConfig } from 'vite';
import { writeFileSync } from 'fs';
import path from 'path';

export default defineConfig({
  build: {
    // 开启资产清单生成
    manifest: true,
    rollupOptions: {
      input: {
        // 手动指定要处理的语言文件
        'locales/en': './src/assets/locales/en.json',
        'locales/de': './src/assets/locales/de.json',
        'locales/ru': './src/assets/locales/ru.json'
      },
      output: {
        // 自定义哈希命名规则
        assetFileNames: 'assets/[name]-[hash][extname]'
      }
    }
  },
  plugins: [
    {
      name: 'generate-locale-manifest',
      // 打包完成后生成语言文件映射清单
      writeBundle() {
        const manifest = require('./dist/manifest.json');
        const localeManifest = {};
        
        Object.entries(manifest).forEach(([key, value]) => {
          if (key.startsWith('locales/')) {
            const lang = key.split('/')[1];
            localeManifest[lang] = value.file;
          }
        });
        
        writeFileSync(
          path.resolve(__dirname, 'dist/locales-manifest.json'),
          JSON.stringify(localeManifest, null, 2)
        );
      }
    }
  ]
});
  1. 前端代码中先加载映射清单,再发起XHR请求:
// 加载语言文件映射
fetch('/locales-manifest.json')
  .then(res => res.json())
  .then(manifest => {
    const targetLang = 'en'; // 替换为当前语言
    return fetch(`/${manifest[targetLang]}`).then(res => res.json());
  })
  .then(localeData => {
    // 使用语言数据
  });

方案三:用静态复制插件自定义哈希处理

适合需要将文件复制到指定目录且保留原有结构的场景:

  1. 安装插件:npm install vite-plugin-static-copy --save-dev
  2. 配置vite.config.js,自定义哈希生成与文件复制逻辑:
// vite.config.js
import { defineConfig } from 'vite';
import { viteStaticCopy } from 'vite-plugin-static-copy';
import crypto from 'crypto';
import fs from 'fs';
import path from 'path';

// 生成文件哈希(可自定义长度)
function generateFileHash(filePath) {
  const fileBuffer = fs.readFileSync(filePath);
  return crypto.createHash('md5').update(fileBuffer).digest('hex').slice(0, 8);
}

export default defineConfig({
  plugins: [
    viteStaticCopy({
      targets: [
        {
          src: 'src/assets/locales/*.json',
          dest: 'assets/locales',
          // 重命名文件时添加哈希
          rename: (name, ext) => {
            const hash = generateFileHash(path.resolve(__dirname, 'src/assets/locales', `${name}${ext}`));
            return `${name}-${hash}${ext}`;
          }
        }
      ]
    }),
    {
      name: 'generate-locale-map',
      writeBundle() {
        const localeDir = path.resolve(__dirname, 'src/assets/locales');
        const localeFiles = fs.readdirSync(localeDir).filter(f => f.endsWith('.json'));
        const localeMap = {};
        
        localeFiles.forEach(file => {
          const lang = file.replace('.json', '');
          const hash = generateFileHash(path.join(localeDir, file));
          localeMap[lang] = `assets/locales/${lang}-${hash}.json`;
        });
        
        writeFileSync(
          path.resolve(__dirname, 'dist/locale-map.json'),
          JSON.stringify(localeMap, null, 2)
        );
      }
    }
  ]
});
  1. 前端通过加载/locale-map.json获取带哈希的文件名,再发起XHR请求即可。

内容的提问来源于stack exchange,提问作者Dieter Pisarewski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 07:45:31