Vite引用本地靜態(tài)資源的正確方式
前言
在前端開發(fā)中,除了通過 API 動(dòng)態(tài)請(qǐng)求的數(shù)據(jù)外,還有一些諸如 HTML 文件、圖片、字體等文件需要在項(xiàng)目中被用到,通常這些被視為靜態(tài)資源。對(duì)于靜態(tài)資源的管理和引用方式有時(shí)也會(huì)產(chǎn)生讓人困惑的問題,就比如在 Vite 構(gòu)建的項(xiàng)目中引用圖片資源時(shí),如果引用方式不正確就可能會(huì)出現(xiàn)意外的 “圖裂” 情況。
本文將基于 Vite + React 來(lái)講述并解鎖 Vite 引用本地靜態(tài)資源的正確姿勢(shì),主要包括 Vite 對(duì)本地資源的靜態(tài)引用和動(dòng)態(tài)引用兩種方式,并結(jié)合一個(gè)案例來(lái)演示動(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
對(duì)應(yīng)@
,src/assets
對(duì)應(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 這類打包工具對(duì)靜態(tài)資源有特定的處理方式,在這里我們需要給引用資源的方式分為兩類:靜態(tài)引入和動(dòng)態(tài)引入。
靜態(tài)引用圖片資源
靜態(tài)引入圖片資源就是使用像 Tailwind CSS、CSS 樣式或者指定<img>
元素的src
屬性這樣的。
需要注意的是在<img>
元素中,src
屬性使用@
路徑別名是無(wú)效的,這是因?yàn)閷?duì)于 Vite 來(lái)說(shuō)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ī)的絕對(duì)路徑:
<img src="/src/assets/images/boat.png" alt="Preview" className='max-w-full max-h-full object-contain' />
<img>
元素指定src
屬性,使用@
路徑別名是無(wú)效的:
<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 模塊中,通過相對(duì)路徑我們就能得到一個(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') } ]
頁(yè)面結(jié)構(gòu)
頁(yè)面結(jié)構(gòu)中,主要分為菜單圖片和菜單的描述文本。
在這里菜單圖標(biāo)是通過行內(nèi)樣式指定圖片路徑的,如果使用靜態(tài)引用的方式那么icon
就是絕對(duì)路徑,如果是動(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)資源常見存放目錄
public
src/assets
- 引用圖片資源的常規(guī)方式
<img>
元素指定src
background: url()
、background-image: url()
樣式- JS 腳本動(dòng)態(tài)指定
src
屬性
- Vite 靜態(tài)引用圖片資源
background: url()
、background-image: url()
樣式<img>
元素指定src
屬性,使用絕對(duì)路徑或相對(duì)路徑
- 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)資源的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue 重塑數(shù)組之修改數(shù)組指定index的值操作
這篇文章主要介紹了vue 重塑數(shù)組之修改數(shù)組指定index的值操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2020-08-08vue實(shí)現(xiàn)類似淘寶商品評(píng)價(jià)頁(yè)面星級(jí)評(píng)價(jià)及上傳多張圖片功能
最近在寫一個(gè)關(guān)于vue的商城項(xiàng)目,然后集成在移動(dòng)端中,開發(fā)需求中有一界面,類似淘寶商城評(píng)價(jià)界面!接下來(lái)通過本文給大家分享vue實(shí)現(xiàn)類似淘寶商品評(píng)價(jià)頁(yè)面星級(jí)評(píng)價(jià)及上傳多張圖片功能,需要的朋友參考下吧2018-10-10vue antd的from表單中驗(yàn)證rules中type的坑記錄
這篇文章主要介紹了vue antd的from表單中驗(yàn)證rules中type的坑記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04vue項(xiàng)目使用jszip和file-saver批量打包壓縮圖片或附件方式
這篇文章主要介紹了vue項(xiàng)目使用jszip和file-saver批量打包壓縮圖片或附件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03vue3的自定義指令directives實(shí)現(xiàn)
本文主要介紹了vue3的自定義指令directives實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07elementui導(dǎo)出數(shù)據(jù)為xlsx、excel表格
本文主要介紹了elementui導(dǎo)出數(shù)據(jù)為xlsx、excel表格,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09vue中data和data()的區(qū)別說(shuō)明
這篇文章主要介紹了vue中data和data()的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03利用Vue的v-for和v-bind實(shí)現(xiàn)列表顏色切換
這篇文章主要介紹了利用Vue的v-for和v-bind實(shí)現(xiàn)列表顏色切換,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2020-07-07