🏞️
Nuxt3でassetsの画像を動的に表示する
TL;DR
import.meta.globEager
を使う。
背景
Nuxt2では、assetsの画像を動的に表示するときは
<img :src="require(hogehoge)">
のようにしていた。
しかし、Nuxt3で使われているViteにはrequire
がないため、この方法が使えない。
環境
MacOS 12.3.1
Node 16.16.0
Nuxt 3.0.0-rc.6
Vite 2.9.14
解決方法
src/lib/images.ts
const images = import.meta.globEager?.('../assets/images/**/*') || {}
const ret: Record<string, string> = {}
for (const key in images) {
ret[key.replace('../assets/images/', '')] = images[key].default
}
export default ret as Readonly<typeof ret>
src/components/base/DynamicImg.vue
<template>
<img :src="internalSrc">
</template>
<script setup lang="ts">
import images from '@/lib/images'
const props = defineProps({
src: {
type: String,
default: ''
}
})
const { src } = toRefs(props)
const internalSrc = computed<string | undefined>(() => images[src.value])
</script>
注意点
import.meta.globEager
はVite 3で非推奨になっている。
今回はViteのバージョンが2.9.14だったので問題なかったが、いずれ書き換えなければいけなくなるかもしれない。
うまくいかなかった方法
最初、この記事の通りにやってみた。
この記事では、新旧2つの方法が紹介されている(2022/08/26現在)。
(1) new URL(...)的なやつ
これ単体では動くのだが、他のモジュールと相性が悪かった。
グローバルにScss変数を使いたかったので、style-resourcesモジュールをNuxt3用に改造して使っていたのだが、なぜかこれと干渉して本番用ビルドができない(nuxi dev
はできた)。
import.meta.url
をコメントアウトして適当な文字列に置き換えるとビルドはできる(もちろん画像のsrcは壊れるが)ので、その辺に問題があるのだろう。たぶん。知らんけど。
(2) vueファイルからの相対パスを渡すやつ
開発環境だとうまくいった。
本番環境では、ビルドは通るが、いざブラウザからアクセスすると壊れていた。
Discussion