[Webpack][Vue.js] 動態編譯 assets 嘗試
在 Vue 開發中,假如我們手上有幾張編號編好的素材圖片,放在專案的/src/assets/
資料夾中。要將它們依序顯示,正常思路下會用v-for
寫出:
1 | <img v-for="i in 3" :src="`./assets/cat${i}.jpg`"> |
結果在 dev-server 圖片就出不來,console 給的訊息是GET http://localhost:8080/assets/cat1.jpg 404 (Not Found)
,初步看來是 Webpack 的 file-loader 不認動態綁定的 src …
當然可以不要用v-for
,無腦交差了事…
1 | <img src="./assets/cat1.jpg"> |
有點 sense 的工程師馬上能嗅出這違反DRY原則。而且需求不會最奇葩、只有更奇葩,假如下來的規格是搭配 Bootstrap 框架,做一組單選 radio ,每個選項值用 v-model
綁定,label 裡必須是對應編號的圖片:
1 | <div class="custom-control custom-radio custom-control-inline mb-2"> |
又臭又長,正常的前端到此會出現頭暈、噁心的臨床反應。更別說今天 UI 好心只給3張圖,哪天需求變成20張圖就能靠代碼行數充充 KPI 呢。
於是開始估狗與嘗試,如何用動態的寫法讓 Webpack 也能正常編譯出來。
靜態資源
一種做法是把素材全當成靜態資源,全部放到與 src 同層級的/static/
資料夾下。
1 | └ vue-project |
1 | <img v-for="i in 3" :src="`static/cat${i}.jpg`"> |
此時圖片就正常顯示了。不過要照開發情境取捨利弊,因為這失去使用 Webpack 幫我們打包的意義,例如圖檔路徑就沒有 hash 指紋讓瀏覽器快取判斷更新時機,或者無法搭配 url-loader 將圖片轉成 base64,參考將檔案放在 static 與 src/assets 的差異。
require()
之後爬了一些文,算是找到比較正統的作法,只要把圖片路徑用require()
去 call 就好:
1 | <img v-for="i in 3" :src="require(`./assets/cat${i}.jpg`)"> |
也可以把它包成 method
1 | <img v-for="i in 3" :src="catImg(i)"> |
1 | methods: { |
圖片也成功編譯到/dist
資料夾,路徑帶有 hash 指紋
只是這方法也有奇怪、但影響不大的 bug … 例如我另外加了 cat4.jpg, cat5.jpg 當成沒被用到的素材,然後npm run build
…
各位觀眾,五隻貓!
跟預想的行為有出入,檔案只用到三張圖卻五張貓都抓進去了,不過沒用到的 logo.png 倒是很正常地沒被編譯,搞不清楚是 file-loader
還是 v-for
的問題,活著好難心好累,至少缺點比用靜態參照的方式還小、可以接受,看日後小精靈會不會幫我找到解答。