Vite動(dòng)態(tài)導(dǎo)入靜態(tài)資源與自動(dòng)依賴發(fā)現(xiàn)過(guò)程
一、Vite 動(dòng)態(tài)導(dǎo)入靜態(tài)資源
在 Vite 中,動(dòng)態(tài)加載圖片、JSON 等靜態(tài)資源是高頻需求,但動(dòng)態(tài)路徑拼接可能導(dǎo)致構(gòu)建失敗或資源未識(shí)別。
以下結(jié)合示例代碼,分析三種實(shí)現(xiàn)方案:
1. 方案一:new URL 動(dòng)態(tài)路徑轉(zhuǎn)換
通過(guò) new URL 拼接路徑,Vite 自動(dòng)處理資源引用:
const pathKey = `../assets/${val}.jpg`;
const src = new URL(pathKey, import.meta.url);
imgSrc.value = src.href;
原理與限制:
- Vite 會(huì)將路徑轉(zhuǎn)換為構(gòu)建后的哈希 URL(如
_assets/1-abc123.jpg)。 - 限制:路徑必須為靜態(tài)字符串模板(如
`../assets/${val}.jpg`),不可使用完全動(dòng)態(tài)變量(如pathKey = '../assets/' + val + '.jpg'),否則構(gòu)建時(shí)無(wú)法解析。
2. 方案二:import() 動(dòng)態(tài)導(dǎo)入
使用 import() 語(yǔ)法按需加載資源:
import(`../assets/${val}.jpg`).then((res) => {
imgSrc.value = res.default;
});
特性:
- 構(gòu)建時(shí),Vite 會(huì)分析
../assets/下的所有.jpg文件,生成對(duì)應(yīng) chunk。 - 問(wèn)題:若
val的取值在構(gòu)建時(shí)無(wú)法確定(如用戶輸入),可能導(dǎo)致資源缺失。
3. 方案三:import.meta.glob 批量預(yù)加載
通過(guò) Glob 模式預(yù)加載所有匹配資源,運(yùn)行時(shí)按需獲?。?/p>
// 預(yù)加載所有 jpg 文件(構(gòu)建時(shí)生成映射表)
const srcs = import.meta.glob("../assets/*.jpg", { as: "url" });
// 運(yùn)行時(shí)動(dòng)態(tài)獲取
const pathKey = `../assets/${val}.jpg`;
const url = await srcs[pathKey]();
imgSrc.value = url;
優(yōu)勢(shì):
- 構(gòu)建時(shí)生成所有資源的 URL 映射表,避免運(yùn)行時(shí)路徑不確定性。
{ as: 'url' }表示直接返回資源 URL,無(wú)需手動(dòng)處理default屬性。
二、代碼示例的問(wèn)題與優(yōu)化
1. 路徑嚴(yán)格匹配問(wèn)題
示例代碼中,pathKey 必須與 Glob 生成的鍵完全一致(如 ../assets/2.jpg)。若文件名含動(dòng)態(tài)前綴(如時(shí)間戳),需調(diào)整 Glob 模式:
// 松散匹配文件名中的數(shù)字
const srcs = import.meta.glob("../assets/[0-9].jpg", { as: "url" });
2. 資源未找到的兜底處理
通過(guò) try/catch 或條件判斷增強(qiáng)健壯性:
try {
const url = await srcs[pathKey]();
imgSrc.value = url;
} catch {
imgSrc.value = fallbackImage; // 加載默認(rèn)圖
}
三、Vite 自動(dòng)依賴發(fā)現(xiàn)的條件
Vite 的依賴預(yù)構(gòu)建(Pre-Bundling)是性能優(yōu)化的核心,其觸發(fā)條件如下:
1. 依賴類型識(shí)別
- CommonJS 模塊:若
node_modules中的依賴未提供 ESM 格式,Vite 自動(dòng)預(yù)構(gòu)建。 - 嵌套依賴:若依賴內(nèi)部引用了其他 CJS 模塊(如
lodash的子包),觸發(fā)預(yù)構(gòu)建。 - 非優(yōu)化入口:依賴的
package.json未指定module或exports字段。
2. 代碼中的導(dǎo)入方式
- 靜態(tài)導(dǎo)入:
import axios from 'axios'會(huì)被自動(dòng)分析。 - 動(dòng)態(tài)導(dǎo)入:
import('lodash')若路徑為字符串字面量,觸發(fā)預(yù)構(gòu)建。 - 完全動(dòng)態(tài)路徑:
import(someVar)不會(huì)觸發(fā)預(yù)構(gòu)建,可能導(dǎo)致運(yùn)行時(shí)加載問(wèn)題。
3. 配置干預(yù)
在 vite.config.js 中手動(dòng)控制依賴:
export default {
optimizeDeps: {
include: ['lodash/debounce'], // 強(qiáng)制預(yù)構(gòu)建特定子模塊
exclude: ['jquery'], // 排除無(wú)需預(yù)構(gòu)建的庫(kù)
},
}
四、實(shí)戰(zhàn):動(dòng)態(tài)資源與依賴預(yù)構(gòu)建的聯(lián)動(dòng)問(wèn)題
場(chǎng)景:動(dòng)態(tài)加載第三方圖標(biāo)庫(kù)
假設(shè)項(xiàng)目中按需加載 @ant-design/icons 的圖標(biāo):
const loadIcon = async (name) => {
const icon = await import(`@ant-design/icons/${name}.js`);
return icon;
};
問(wèn)題:Vite 默認(rèn)不會(huì)預(yù)構(gòu)建 @ant-design/icons 的子模塊,導(dǎo)致運(yùn)行時(shí)加載延遲。
解決方案:
在配置中顯式聲明需要預(yù)構(gòu)建的子模塊:
// vite.config.js
export default {
optimizeDeps: {
include: ['@ant-design/icons/HomeOutlined'],
},
}
五、總結(jié)與最佳實(shí)踐
1. 動(dòng)態(tài)資源加載
- 優(yōu)先使用
import.meta.glob:提前聲明資源范圍,避免路徑不確定性。 - 統(tǒng)一資源目錄:如將所有動(dòng)態(tài)圖片放在
src/assets/dynamic/下,通過(guò) Glob 簡(jiǎn)化匹配。 - 處理未找到資源:添加日志與兜底邏輯,提升用戶體驗(yàn)。
2. 依賴預(yù)構(gòu)建優(yōu)化
- 監(jiān)控控制臺(tái)輸出:運(yùn)行
vite build時(shí),檢查哪些依賴被自動(dòng)預(yù)構(gòu)建。 - 按需手動(dòng)包含:對(duì)大型庫(kù)的子模塊(如
lodash、antd),通過(guò)include減少構(gòu)建體積。 - 慎用
exclude:除非明確知曉依賴的模塊格式,否則避免盲目排除。
3. 調(diào)試工具推薦
- 構(gòu)建分析:使用
rollup-plugin-visualizer查看產(chǎn)物結(jié)構(gòu)。 - 依賴檢查:運(yùn)行
npx vite deps查看預(yù)構(gòu)建的依賴列表。
通過(guò)上述實(shí)踐,開(kāi)發(fā)者可以高效管理 Vite 中的動(dòng)態(tài)資源,同時(shí)精準(zhǔn)控制依賴預(yù)構(gòu)建策略,實(shí)現(xiàn)性能與可維護(hù)性的最佳平衡。
<template>
<div>
<el-switch
v-model="value"
:active-value="2"
:inactive-value="1"
active-color="#13ce66"
inactive-color="#ff4949"
@change="handleChange"
>
</el-switch>
<img :src="imgSrc" alt="" />
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
// import a from "../assets/1.jpg";
// console.log("a", a);
const value = ref(1);
const imgSrc = ref("");
const handleChange = async (val: any) => {
console.log(val);
// const src = new URL(`../assets/${val}.jpg`, import.meta.url);
// console.log("src", src);
// imgSrc.value = src.href;
// import("../assets/" + val + ".jpg").then((res) => {
// console.log("res", res);
// imgSrc.value = res.default;
// });
const srcs = import.meta.glob("../assets/*.jpg", { as: "url" });
console.log("srcs", srcs);
// 構(gòu)建對(duì)應(yīng)的路徑 key(注意文件名匹配要完全一致)
const pathKey = `../assets/${val}.jpg`;
try {
const url = await srcs[pathKey]();
imgSrc.value = url;
} catch {
imgSrc.value = ""; // 加載默認(rèn)圖
}
};
</script>
<style lang="scss" scoped>
img {
width: 1200px;
height: 600px;
}
</style>
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
基于Vue3實(shí)現(xiàn)無(wú)限滾動(dòng)組件的示例代碼
如果你在社交媒體上停留的時(shí)間過(guò)長(zhǎng),那么,你所在的網(wǎng)站很可能正在使用無(wú)限滾動(dòng)組件。這篇文章教你利用Vue3實(shí)現(xiàn)無(wú)限滾動(dòng)組件,感興趣的可以參考一下2022-09-09
Vue實(shí)現(xiàn)下拉滾動(dòng)加載數(shù)據(jù)的示例
這篇文章主要介紹了Vue實(shí)現(xiàn)下拉滾動(dòng)加載數(shù)據(jù)的示例,幫助大家更好的理解和學(xué)習(xí)使用vue框架,感興趣的朋友可以了解下2021-04-04
vue data有值,但是頁(yè)面{{}} 取不到值的解決
這篇文章主要介紹了vue data有值,但是頁(yè)面{{}} 取不到值的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11
vue3.0中給自己添加一個(gè)vue.config.js配置文件
這篇文章主要介紹了vue3.0中給自己添加一個(gè)vue.config.js配置文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07

