在 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 在引用这样的文件时不要使用参数,或者是否有其他方法可以将哈希添加为查询参数?
我也遇到了同样的问题,我写了一个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))
}
}
})