[Vite] 靜態資源的動態訪問
前言
這篇筆記是對渡一教育網課的知識點總結,源視頻?? 靜態資源的動態訪問【渡一教育】 。
靜態資源與打包規則
Vite腳手架在打包代碼的時候,會把源代碼里對于靜態資源的訪問路徑轉換為打包后靜態資源文件的路徑。主要的區別是文件指紋,即打包后的文件會帶上一個hash值,用于區分不同版本的文件。
文件指紋的作用:
客戶端會緩存文件。當前端項目更新之后,重新打包、部署,由于文件指紋的存在,客戶端檢測到文件名不同,則會下載新版的文件。如果沒有文件指紋,且新舊版文件名一致,客戶端會讀緩存,而不能及時地拿到新版文件。
動態訪問靜態資源
動態訪問靜態資源通常導致讀取不到文件,因為源代碼中使用的路徑是src中的,而打包之后靜態資源帶上了文件指紋,代碼中的路徑卻沒有隨之改變。
如下情景屬于對靜態資源的動態訪問,也就是說使用了插值語法,而變量值只有在代碼執行中才被確定:
css中的background-image: url()使用v-bind動態地綁定一張圖片的路徑;template中節點的style,在background-image:url()使用插值語法;img節點的src屬性使用動態綁定傳遞圖片路徑。
方法一:直接導入
import img1 from './assets/1.jpg';
import img2 from './assets/2.jpg';
...
const imgName = ref('');
function handleChange(val){
if(val === 1){
imgName.value = img1;
}else if(...){
...
}
}
<img :src="imgName" />
將所有可能用到的圖片都導入,并配合if語句實現動態切換。
缺點:
- 代碼臃腫,難以維護。
方法二:靜態資源轉移到Public目錄
轉移到public目錄的靜態資源文件會原封不動地被打包到dist文件夾中,不用擔心文件名發生變化,在源代碼中直接使用絕對路徑訪問靜態資源即可:/assets/1.jpg。
但缺點就是失去了文件指紋帶來的好處,后期如果靜態資源被替換了,但是文件名沒變,客戶端仍讀取緩存,無法及時獲取最新版的靜態資源。
方法三:動態導入
const imgName = ref('');
const url = ref('');
watchEffect(async()=>{
const module = await import('./assets/${imgName.value}.jpg');
console.log(module);
// ...后續操作
});
Vite腳手架在靜態分析代碼的時候,讀取到動態導入import(),且內部是模板字符串,只有一部分內容是動態的,那么Vite會自動將符合./assets/*.jpg路徑格式的靜態資源全部進行打包。
在打包的時候,不僅會打包所有符合情況的靜態資源,還會打包出對應的.js文件。import()語句實際上是導入.js文件,而.js文件又默認導出打包后的靜態資源文件路徑。


缺點:
- 打包結果多出許多
.js文件; - 異步導入。
方法四:URL構造函數
使用計算屬性computed和URL。
const url = computed(()=>{
const obj = new URL(`./assets/${imgName.value}.jpg`, import.meta.url);
return obj.pathname;
});
URL傳入兩個參數:1. 文件路徑;2. 基準路徑。
返回URL實例對象的pathname屬性,即是打包后的文件路徑。
<div :style="{backgroundImage: url(url)}">
</div>
原理:
單文件組件在進行打包的時候,會分析以下內容:
<img>標簽的src屬性;css的background-image屬性的url()函數;
1和2:如果是靜態的,則會進行路徑轉換。
import();new URL();
3和4:可以是動態的,但是只能是某一個部分是動態的。通常是模板字符串。這種情況下會把指定文件夾下面的指定格式的文件全部打包,并進行路徑轉換。3會生成額外的.js文件,4不會。
總結
以上的方法中,使用URL的方法是最優的。
- 支持動態導入;
- 保留文件指紋;
- 不會產生額外的
.js文件; - 同步代碼。

浙公網安備 33010602011771號