項(xiàng)目遷移vite引入圖片資源報(bào)require?is?not?defined問(wèn)題的解決辦法
前言
Vite是一種輕量快速的前端構(gòu)建工具,能夠顯著提升前端開發(fā)體驗(yàn),而且官方已經(jīng)發(fā)布v4版本,相對(duì)比較穩(wěn)定。在把VueCli搭建的項(xiàng)目遷移到Vite的過(guò)程中遇到了個(gè)問(wèn)題,下面分享一下問(wèn)題及解決辦法。
一、遇到的問(wèn)題
在script
標(biāo)簽里面引入的圖片資源沒(méi)生效,然后一看控制臺(tái),報(bào)錯(cuò)顯示 require is not defined …
二、解決辦法
1. 明確方向
經(jīng)過(guò)查找Vite相關(guān)文檔,看到官方文檔靜態(tài)資源處理目錄,發(fā)現(xiàn)需要使用new URL()
這個(gè)方法才能處理動(dòng)態(tài)引入的URL,才能保證圖片資源在經(jīng)過(guò)打包和資源哈希后仍指向正確的地址。
2. 解決方法
① 方案一
既然如此,那么直接改為new URL() 的寫法。
原本寫法是:
url: require("../assets/images/banner@2x.png"),
- 那么使用
new URL()
的寫法:
url: new URL(`../assets/images/banner@2x.png`, import.meta.url).href;
- 或者是
import
的寫法 :
import banner from "../assets/images/banner@2x.png"; url: banner,
② 方案二
由于上面的方法都要一個(gè)個(gè)修改過(guò)于麻煩了,而且項(xiàng)目圖片都位于src/assets/images/
下,那么直接封裝成一個(gè)函數(shù),像hooks那樣調(diào)用應(yīng)該方便很多。
- 在utils文件下下新建useImgUrl.js文件,簡(jiǎn)簡(jiǎn)單單,只需要傳入圖片文件名及類型即可
const getImgUrl = file => { return new URL(`../assets/images/${file}`, import.meta.url).href; }; export default getImgUrl;
- 在文件中引入并使用,文件內(nèi)修改只需使用全局替換功能即可
import getImgUrl from "../utils/useImgUrl"; url: getImgUrl("banner@2x.png"),
③ 方案三
上面的方案雖然不用一個(gè)個(gè)改了,但是Vue3沒(méi)有mixins
這樣可以全局引入的方法,還是需要在不同的文件去引入hook,這個(gè)時(shí)候我想能不能像webpack
的loader
那樣去全局處理.vue
文件,這樣全局替換的操作交給構(gòu)建工具去自動(dòng)執(zhí)行得了,然后發(fā)現(xiàn)Vite里面并沒(méi)有loader
配置,不過(guò)好在這時(shí)候一個(gè)Vite插件給了我靈感,可以用Vite插件API去實(shí)現(xiàn)類似的功能,于是轉(zhuǎn)換下思路,寫了這么一個(gè)插件
- 代碼:
// requireToUrlPlugin.js export default function requirePlugin() { return { // 插件名稱 name: "vite-plugin-vue-requireToUrlPlugin", // 默認(rèn)值post:在 Vite 核心插件之后調(diào)用該插件,pre:在 Vite 核心插件之前調(diào)用該插件 // enforce: "post", // 代碼轉(zhuǎn)譯,這個(gè)函數(shù)的功能類似于 "webpack" 的 "loader" transform(code, id, opt) { const vueRE = /\.vue$/; const require = /require/g; // 過(guò)濾掉非目標(biāo)文件 if (!vueRE.test(id) || !require.test(code)) return code; // 匹配 require() 內(nèi)的內(nèi)容 const requireRegex = /require\((.*?)\)/g; // 將 require() 內(nèi)的內(nèi)容替換為 new URL 的寫法 const finalCode = code.replace(requireRegex, "new URL($1,import.meta.url).href"); // 將轉(zhuǎn)換后的代碼返回 return finalCode; }, }; }
- 在Vite配置中引入此插件:
// vite.config.js import requireToUrlPlugin from './src/requireToUrlPlugin'; export default defineConfig(({ command, mode }) => { plugins: [ vue(), requireToUrlPlugin(), ] });
引入后項(xiàng)目中的require方法都會(huì)被插件自動(dòng)轉(zhuǎn)換為new URL() 的語(yǔ)法,真的是終極大招[doge],這樣就不用再一個(gè)個(gè)文件去改了,非常省事,而且自己寫的插件也完全可以自由定制,寫法僅供參考。
通過(guò)查看控制臺(tái)能看到通過(guò)Vite的打包運(yùn)行“preview”后,圖片是正常顯示的。
查看源代碼能看到原本寫的 require 方法已經(jīng)變成了 new URL()的方法。
三、原因及相關(guān)原理
1. 為什么需要require方法
靜態(tài)資源就是直接存放在項(xiàng)目中的資源,這些資源不需要我們發(fā)送專門的請(qǐng)求進(jìn)行獲取。比如assets目錄下面的圖片,視頻,音頻,字體文件,css樣式表等。
動(dòng)態(tài)資源就是需要發(fā)送請(qǐng)求獲取到的資源
答:因?yàn)轫?xiàng)目引入的動(dòng)態(tài)資源被當(dāng)做靜態(tài)資源處理了。被打包過(guò)后,被打包在新的文件夾下的圖片資源會(huì)生成新的文件名,在原來(lái)的文件名后會(huì)加入一串?dāng)?shù)字,此即為資源哈?;?,是為了做服務(wù)器緩存用的。那么靜態(tài)的路徑并不能匹配到新的文件名,導(dǎo)致無(wú)法正確的引入資源,所以需要加上require。require 是一個(gè)node方法,webpack會(huì)將圖片當(dāng)成一個(gè)模塊,并根據(jù)配置文件中的規(guī)則進(jìn)行打包,通過(guò)require方法拿到的文件地址,就是資源文件編譯過(guò)后的文件地址。
2. 為什么require方法失效了
答:因?yàn)樵瓉?lái)的項(xiàng)目是VueCli搭建的,其是構(gòu)建于 webpack 和 webpack-dev-server 之上的,所以require方法會(huì)經(jīng)過(guò)webpack
處理,而Vite開發(fā)環(huán)境是基于原生ES Module
的,生產(chǎn)環(huán)境則是通過(guò)Rollup
進(jìn)行打包的,Rollup默認(rèn)也是不支持CommonJS
模塊的,所以無(wú)法識(shí)別 require 方法。
3. new URL() 為什么就可以
const imgUrl = new URL('./img.png', import.meta.url).href
new URL(url,base)用來(lái)創(chuàng)建一個(gè)新 URL 對(duì)象:
- url —— 完整的 URL,或者僅路徑(如果設(shè)置了 base)
- base —— 可選的 base URL:如果設(shè)置了此參數(shù),且參數(shù) url 只有路徑,則會(huì)根據(jù)這個(gè) base 生成 URL
其中有一個(gè)屬性是href,正好是函數(shù)的返回值!
import.metaimport.meta 對(duì)象包含關(guān)于當(dāng)前模塊的信息。
它的內(nèi)容取決于其所在的環(huán)境。在瀏覽器環(huán)境中,它包含當(dāng)前腳本的 URL,或者如果它是在 HTML 中的話,則包含當(dāng)前頁(yè)面的 URL。
4. Vite插件介紹
Vite 插件擴(kuò)展了設(shè)計(jì)出色的 Rollup 接口,帶有一些 Vite 獨(dú)有的配置項(xiàng)。因此,只需要編寫一個(gè) Vite 插件,就可以同時(shí)為開發(fā)環(huán)境和生產(chǎn)環(huán)境工作。
擴(kuò)展閱讀
總結(jié)
以上就是全部?jī)?nèi)容,本文簡(jiǎn)單介紹了Vite在生產(chǎn)構(gòu)建時(shí)JavaScript模塊對(duì)圖片資源的引入方法,并且介紹了Vite插件的基本用法。
到此這篇關(guān)于項(xiàng)目遷移vite引入圖片資源報(bào)require is not defined問(wèn)題的解決辦法的文章就介紹到這了,更多相關(guān)vite報(bào)錯(cuò)require is not defined內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在vue中多次調(diào)用同一個(gè)定義全局變量的實(shí)例
今天小編就為大家分享一篇在vue中多次調(diào)用同一個(gè)定義全局變量的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09Vue實(shí)現(xiàn)自定義字段導(dǎo)出EXCEL的示例代碼
這篇文章主要介紹了Vue實(shí)現(xiàn)自定義字段導(dǎo)出EXCEL的示例代碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08vue@cli3項(xiàng)目模板怎么使用public目錄下的靜態(tài)文件
這篇文章主要介紹了vue@cli3項(xiàng)目模板怎么使用public目錄下的靜態(tài)文件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07Vue3導(dǎo)入Elementplus時(shí)組件無(wú)法加載的情況及解決
這篇文章主要介紹了Vue3導(dǎo)入Elementplus時(shí)組件無(wú)法加載的情況及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助2024-03-03在vue2?中使用?tailwindcss的方法?親測(cè)可用
這篇文章主要介紹了在vue2?中使用?tailwindcss的方法?親測(cè)可用,本文分步驟給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07Vue3中Vite和Vue-cli的特點(diǎn)與區(qū)別詳解
vue-cli是Vue早期推出的一款腳手架,使用webpack創(chuàng)建Vue項(xiàng)目,可以選擇安裝需要的各種插件,比如Vuex、VueRouter,下面這篇文章主要給大家介紹了關(guān)于Vue3中Vite和Vue-cli的特點(diǎn)與區(qū)別的相關(guān)資料,需要的朋友可以參考下2022-12-12