Vite 缓存清除使用查询参数而不是文件名

问题描述 投票:0回答:1

在 Vite 中,是否可以使用查询参数进行缓存清除(而不是文件名中的哈希)? 我当前的配置如下所示:

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(),
    ],
    base: '/frontend',
    build: {
        outDir: '../www/public/frontend/',
        emptyOutDir: true,
        rollupOptions: {
            output: {
                entryFileNames: 'assets/[name]-[hash].js',
                chunkFileNames: 'assets/[name]-[hash].js',
                assetFileNames: 'assets/[name]-[hash].[ext]',
            },
        },
    },
    resolve: {
        alias: {
            '@': fileURLToPath(new URL('./src', import.meta.url)),
        },
    },
});

当我更改 assetFileNames 以使用哈希作为 url 参数时,我会遇到编译错误

assetFileNames: 'assets/[name].[ext]?v=[hash]',

错误看起来像这样:

ENOENT: no such file or directory, open ' ... some absolute path here ... \site\www\public\frontend\assets\someCss.css?v=82315f25'

有没有办法告诉 Vite 在引用这样的文件时不要使用参数,或者是否有其他方法可以将哈希添加为查询参数?

config vite rollupjs
1个回答
0
投票

我也遇到了同样的问题,我写了一个Vite插件来实现这个功能。它对我来说效果很好,希望对你也有帮助。

import { rename, writeFile } from 'fs/promises'
import path from 'path'
import { Plugin } from 'vite'

const DIST_PATH = path.join(process.cwd(), 'dist')
const ENTRY_FILE_NAME = 'index.html'
const NEED_TRANSFORM_EXT: readonly string[] = ['.html', '.js', '.css']
const HASH_LENGTH = 8

interface FileInfo {
  fullName: string
  name: string
  hash: string
  ext: string
}

export default function (): Plugin {
  return {
    name: 'transform-hash',
    async writeBundle(_, bundle) {
      const fileInfoByPath = new Map<string, FileInfo>()
      for (const filePath of Object.keys(bundle)) {
        if (filePath === ENTRY_FILE_NAME) {
          continue
        }
        fileInfoByPath.set(filePath, extractFileInfo(filePath))
      }
      for (const [filePath, bundleInfo] of Object.entries(bundle)) {
        if (!NEED_TRANSFORM_EXT.includes(path.extname(filePath))) {
          continue
        }
        // @ts-ignore
        let codeOrSource: string = bundleInfo.code ?? bundleInfo.source
        for (const fileInfo of fileInfoByPath.values()) {
          codeOrSource = codeOrSource.replaceAll(
            fileInfo.fullName,
            `${fileInfo.name}${fileInfo.ext}?${fileInfo.hash}`
          )
        }
        await writeFile(path.join(DIST_PATH, filePath), codeOrSource)
      }
      for (const [filePath, fileInfo] of fileInfoByPath) {
        await rename(
          path.join(DIST_PATH, filePath),
          path.join(DIST_PATH, `${path.dirname(filePath)}/${fileInfo.name}${fileInfo.ext}`)
        )
      }
    }
  }
}

function extractFileInfo(filePath: string): FileInfo {
  const fileName = path.basename(filePath)
  const ext = path.extname(fileName)
  const nameWithHash = path.basename(fileName, ext)
  return {
    fullName: fileName,
    name: nameWithHash.slice(0, -(HASH_LENGTH + 1)),
    hash: nameWithHash.slice(-HASH_LENGTH),
    ext
  }
}

vite.config.ts

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import transfromHash from './plugins/transform-hash'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), vueJsx(), transfromHash()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})
© www.soinside.com 2019 - 2024. All rights reserved.