【Vite】静态资源的动态访问
一、Vite处理静态资源的机制
Vite在构建时会对静态资源路径进行转换,并添加文件指纹(哈希值),例如将1.jpg
转换为1-abc123.jpg
。这解决了客户端缓存更新问题,但在某些情况下也导致动态路径无法被构建工具静态分析。
链接:静态资源处理
动态访问的典型场景:
• CSS中使用插值语法设置background-image: url()
,或者CSS中通过v-bind
动态绑定路径。
• <img>
标签的src
属性绑定;
• import 语句导入。
• URL 。
二、动态访问静态资源的实现方案
- 直接导入所有资源(不推荐)
通过import
手动导入所有可能用到的资源,再根据条件动态切换:
import img1 from './assets/1.jpg';
import img2 from './assets/2.jpg';
const imgName = ref('');
function handleChange(val) {imgName.value = val === 1 ? img1 : img2;
}
• 优点:简单直接,保留文件指纹。
• 缺点:代码臃肿,维护困难,无法应对大量资源。
- 将资源放入
public
目录(不推荐)
将静态资源存放在public
目录下,直接通过绝对路径访问:
<img :src="`/public/assets/${name}.jpg`" />
• 优点:路径固定,无需处理动态路径。
• 缺点:失去文件指纹,客户端可能缓存旧资源。
- 动态导入(
import()
语法)
使用动态导入语法按需加载资源:
watchEffect(async () => {const module = await import(`./assets/${imgName.value}.jpg`);url.value = module.default;
});
• 原理:Vite会分析./assets/*.jpg
路径,预打包所有匹配资源并生成.js
文件。
• 优点:支持部分动态路径(需为模板字符串)。
• 缺点:生成额外.js
文件,异步加载可能影响性能。
new URL
构造函数(推荐)
利用URL
构造函数动态生成路径:
const url = computed(() => {return new URL(`./assets/${imgName.value}.jpg`, import.meta.url).href;
});
• 原理:基于当前模块的基准路径(import.meta.url
)拼接动态路径,Vite自动处理为构建后的哈希路径。
• 优点:同步操作,保留文件指纹,无额外文件生成。
• 限制:路径必须为模板字符串(如`./assets/${name}.jpg`
),不可完全动态拼接(如'./assets/' + name + '.jpg'
)。
import.meta.glob
批量预加载(推荐)
通过Glob模式预加载所有匹配资源,运行时按需获取:
const images = import.meta.glob('../assets/*.jpg', { as: 'url' });
const pathKey = `../assets/${val}.jpg`;
const url = await images[pathKey]();
• 原理:构建时生成资源URL映射表,运行时直接查询。
• 优势:避免路径不确定性,支持复杂匹配(如../assets/[0-9].jpg
)。
• 扩展:可结合try/catch
处理资源未找到的兜底逻辑。
三、最佳实践与注意事项
-
推荐方案:
• 优先使用new URL
:适用于简单动态路径,兼顾文件指纹和同步加载。• 复杂场景用
import.meta.glob
:适合大量资源或动态前缀/后缀的情况。 -
路径限制:
• Vite要求动态路径中至少包含静态部分(如./assets/${name}.jpg
),否则无法解析。 -
兜底处理:
try {url.value = await images[pathKey](); } catch {url.value = fallbackImage; // 加载默认图 }
四、总结
new URL
和import.meta.glob
是较优解,前者适合简单场景,后者适用于批量处理。若对文件指纹无要求,可短期使用public
目录方案,但需权衡缓存问题。