Vite引用本地靜態(tài)資源的正確方式
前言
在前端開發(fā)中,除了通過 API 動(dòng)態(tài)請求的數(shù)據(jù)外,還有一些諸如 HTML 文件、圖片、字體等文件需要在項(xiàng)目中被用到,通常這些被視為靜態(tài)資源。對于靜態(tài)資源的管理和引用方式有時(shí)也會(huì)產(chǎn)生讓人困惑的問題,就比如在 Vite 構(gòu)建的項(xiàng)目中引用圖片資源時(shí),如果引用方式不正確就可能會(huì)出現(xiàn)意外的 “圖裂” 情況。
本文將基于 Vite + React 來講述并解鎖 Vite 引用本地靜態(tài)資源的正確姿勢,主要包括 Vite 對本地資源的靜態(tài)引用和動(dòng)態(tài)引用兩種方式,并結(jié)合一個(gè)案例來演示動(dòng)態(tài)引用資源的實(shí)現(xiàn)過程。
靜態(tài)資源目錄結(jié)構(gòu)
靜態(tài)資源的存放位置基本上是約定俗成的,public目錄和src/assets。
public:目錄中一般會(huì)放著index.html和favicon.ico。src/assets:而其他業(yè)務(wù)編碼中會(huì)使用的靜態(tài)資源,如圖片、字體等會(huì)統(tǒng)一放在src的assets目錄下。
比如這是我所開發(fā)的一個(gè)項(xiàng)目中所用到的部分圖片資源:

引用圖片資源的常規(guī)方式
在基礎(chǔ)前端項(xiàng)目開發(fā)中,通常會(huì)用到三種常規(guī)的加載圖片的方式,<img>元素、background樣式、JS 腳本動(dòng)態(tài)指定src屬性。
<img>:在 HTML中通過<img>元素指定src引用圖片資源。
<img src="./assets/logo.png" alt="" />
background:通過background: url()或background-image: url()引用本地資源。
#logo {
background: url('./assets/logo.png');
}
#logo {
background-image: url('./assets/logo.png');
}
- JS 腳本動(dòng)態(tài)指定圖片
src屬性。
document.getElementById('logo').src = './assets/logo.png'
配置路徑別名 @assets
為了更靈活地引用項(xiàng)目中的靜態(tài)資源,往往會(huì)給特定的路徑配置別名以方便引用,比如常見的src對應(yīng)@,src/assets對應(yīng)@assets。
如果項(xiàng)目中使用 Vite 構(gòu)建,可以在vite.config.ts中作如下配置:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
base: './',
plugins: [react()],
resolve: {
alias: {
'@': path.join(__dirname, './src'),
'@assets': path.join(__dirname, './src/assets'),
},
},
});
Vite 項(xiàng)目中引用圖片資源
在以 Vite 為底層構(gòu)建的 React 項(xiàng)目中引用圖片資源就不能再同于以往常規(guī)的方式了(這也包括以 Webpack 為底層構(gòu)建的 CRA 項(xiàng)目)。
由于 Vite 或者 Webpack 這類打包工具對靜態(tài)資源有特定的處理方式,在這里我們需要給引用資源的方式分為兩類:靜態(tài)引入和動(dòng)態(tài)引入。
靜態(tài)引用圖片資源
靜態(tài)引入圖片資源就是使用像 Tailwind CSS、CSS 樣式或者指定<img>元素的src屬性這樣的。
需要注意的是在<img>元素中,src屬性使用@路徑別名是無效的,這是因?yàn)閷τ?Vite 來說src中的內(nèi)容就是單純的字符串,即使是配置了路徑別名也并不會(huì)當(dāng)做資源文件去處理;當(dāng)然如果想使用@路徑別名指定src也是有方法的,這時(shí)則需要通過動(dòng)態(tài)引入的方式。
- Tailwind CSS:
<div className='
w-full h-full
bg-[url("@assets/images/boat.png")]
bg-contain bg-no-repeat bg-center'>
</div>
- CSS:
div {
background-image: url("@assets/images/boat.png");
}

<img>元素指定src屬性,使用常規(guī)的絕對路徑:
<img src="/src/assets/images/boat.png" alt="Preview" className='max-w-full max-h-full object-contain' />
<img>元素指定src屬性,使用@路徑別名是無效的:
<img src="@assets/images/boat.png" alt="Preview" className='max-w-full max-h-full object-contain' />

動(dòng)態(tài)引用圖片資源
動(dòng)態(tài)引用圖片資源就是用import、new URL(url, import.meta.url)這樣的方式。
import.meta.url是一個(gè) ESM 的原生功能,會(huì)暴露當(dāng)前模塊的 URL。將它與原生的 URL 構(gòu)造器組合使用,在一個(gè) JavaScript 模塊中,通過相對路徑我們就能得到一個(gè)被完整解析的靜態(tài)資源 URL。
import:Vite 中引入一個(gè)靜態(tài)資源會(huì)返回解析后的公共路徑,生產(chǎn)構(gòu)建后生成散列文件名:
import boatImage from '@assets/images/boat.png';
const Main = () => {
return (
<img
src={boatImage}
alt="Preview"
className='max-w-full max-h-full object-contain'
/>
);
};
export default Main;

new URL(url, import.meta.url):
const boatImage = new URL('@assets/images/boat.png', import.meta.url).href;
const Main = () => {
return (
<img
src={boatImage}
alt="Preview"
className='max-w-full max-h-full object-contain'
/>
);
};
export default Main;

Vite 動(dòng)態(tài)引用本地圖片案例
我們以一個(gè)菜單列表為案例演示 Vite 項(xiàng)目中動(dòng)態(tài)引用圖片資源。在業(yè)務(wù)需求中,菜單列表中會(huì)展示固定的一些圖標(biāo),這些就是本地圖片資源。
菜單數(shù)據(jù)列表
在菜單數(shù)據(jù)列表中,icon屬性就是本地圖片路徑,這里用了一個(gè)自定義函數(shù)獲取,后面會(huì)給到。
const menuItems = [
{
id: 'profile',
name: 'Profile',
icon: getAssetsFile('menu/Profile.png')
},
{
id: 'favorites',
name: 'Favorites',
icon: getAssetsFile('menu/Favorites.png')
}
]
頁面結(jié)構(gòu)
頁面結(jié)構(gòu)中,主要分為菜單圖片和菜單的描述文本。
在這里菜單圖標(biāo)是通過行內(nèi)樣式指定圖片路徑的,如果使用靜態(tài)引用的方式那么icon就是絕對路徑,如果是動(dòng)態(tài)引用,那么icon的路徑就是需要通過new URL()獲取。
<div className='flex w-[72px] h-full pt-[24px] pr-0 pb-[24px] pl-0 flex-col gap-[24px] items-center flex-nowrap bg-[#fff] border-solid border-r border-r-[rgba(0,0,0,0.1)] absolute top-[64px] left-0 overflow-hidden z-[36]'>
{menuItems.map((item) => (
<div
key={item.id}
className={`flex h-[49px] flex-col justify-center items-center self-stretch shrink-0 flex-nowrap relative cursor-pointer border-l-4 ${activeMenu === item.id ? 'border-l-[#ffd05a]' : 'border-l-transparent'}`}
onClick={() => handleMenuClick(item.id)}
>
{/* 菜單圖標(biāo) */}
<div
className="w-[32px] h-[32px] shrink-0 bg-cover bg-no-repeat relative overflow-hidden"
style={{ backgroundImage: `url(${item.icon})` }}
/>
{/* 菜單描述 */}
<span className="h-[20px] shrink-0 basis-auto font-['Inter'] text-[14px] font-normal leading-[20px] text-[#323232] relative text-left whitespace-nowrap">
{item.name}
</span>
</div>
))}
</div>
動(dòng)態(tài)獲取圖片路徑
前面我們提到icon的路徑是由一個(gè)自定義函數(shù)getAssetsFile獲取的。實(shí)際上就是通過new URL()的方式動(dòng)態(tài)獲取圖片路徑。
// 獲取assets靜態(tài)資源
export const getAssetsFile = (url: string) => {
return new URL(`../assets/images/${url}`, import.meta.url).href;
};

回顧總結(jié)
最后回顧總結(jié)一下:
- 靜態(tài)資源常見存放目錄
publicsrc/assets
- 引用圖片資源的常規(guī)方式
<img>元素指定srcbackground: url()、background-image: url()樣式- JS 腳本動(dòng)態(tài)指定
src屬性
- Vite 靜態(tài)引用圖片資源
background: url()、background-image: url()樣式<img>元素指定src屬性,使用絕對路徑或相對路徑
- Vite 動(dòng)態(tài)引用圖片資源
import導(dǎo)入new URL(url, import.meta.url)
以上就是Vite引用本地靜態(tài)資源的正確方式的詳細(xì)內(nèi)容,更多關(guān)于Vite引用本地靜態(tài)資源的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
VueCLI通過process.env配置環(huán)境變量的實(shí)現(xiàn)
本文主要介紹了VueCLI通過process.env配置環(huán)境變量的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
vue滾動(dòng)條滾動(dòng)到頂部或者底部的方法
這篇文章主要給大家介紹了關(guān)于vue滾動(dòng)條滾動(dòng)到頂部或者底部的相關(guān)資料,文中通過代碼示例介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08
Vue中的基礎(chǔ)過渡動(dòng)畫及實(shí)現(xiàn)原理解析
這篇文章主要介紹了Vue中的基礎(chǔ)過渡動(dòng)畫原理解析,需要的朋友可以參考下2018-12-12
Vue.js 實(shí)現(xiàn)數(shù)據(jù)展示全部和收起功能
這篇文章主要介紹了Vue.js 實(shí)現(xiàn)數(shù)據(jù)展示全部和收起功能,代碼簡單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09
詳解Vue一個(gè)案例引發(fā)「內(nèi)容分發(fā)slot」的最全總結(jié)
這篇文章主要介紹了詳解Vue一個(gè)案例引發(fā)「內(nèi)容分發(fā)slot」的最全總結(jié),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12
vue與electron實(shí)現(xiàn)進(jìn)程間的通信詳情
這篇文章主要介紹了vue與electron實(shí)現(xiàn)進(jìn)程間的通信詳情,本文主要介紹electron渲染進(jìn)程和主進(jìn)程間的通信,以及在渲染進(jìn)程和主進(jìn)程中常用的配置項(xiàng),需要的朋友可以參考一下2022-09-09
vue實(shí)現(xiàn)綁定事件的方法實(shí)例代碼詳解
這篇文章主要介紹了vue實(shí)現(xiàn)綁定事件的方法實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-06-06
關(guān)于vue中element-ui?form或table?lable換行的問題
這篇文章主要介紹了vue中element-ui?form或table?lable換行的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Electron+Vue3+Vite搭建桌面應(yīng)用的示例代碼
本文主要介紹了Electron+Vue3+Vite搭建桌面應(yīng)用的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07

