parcel + vue という環境において、 vue コンポーネント内で画像などのパスを動的に組み立てる場合に起こる問題の対処方法

最初は :src="'public/images/' + logo + '.svg'" というようにして動的にパスを構築しようとしたのだが、こうしてしまうと parcel によるバンドル時に解決対象になってくれないようだった。そうなると、バンドル後に全てのファイルは "name.8a64909c.ext" というファイル名に置き換えられるので、ファイルが見つからないということになる。

ということで困っていたのだが、以下のサイトの情報で解決した。

簡単に説明しておくと、component 内で import images from '../public/images/*.svg' とすることによって、元の名前とバンドル後の修正されたファイル名との対応表となるマップを得ることができる。バンドル後のフォルダ構成はフラットな(階層が存在しない)形になっているので <img :src="images[name]"> という形でパスを渡してあげれば無事読み込むことができる、ということだった。

参考に全体も載せておく、実際のコードからとはいえ、note 上で適当に切り出したので、何かミスがありそのままコピーしても動かないかもしれません。

// App.vue
<template>
  <div class="container">
    <div class="customers">
      <Customer v-for="c in customers" :name="c.name" :text="c.text"></Customer>
    </div>
  </div>
</template>

<script>
import Customer from './components/Customer'

export default {
  components: {
    Customer
  },
  data () {
    return {
      customers: [
        {
          name: 'c1',
          text: 'text1'
        },
        {
          name: 'c2',
          text: 'text2'
        },
      ]
    }
  }
}


// Customer.vue
<template>
<div class="customer-card">
  <div class="customer-icon">
    <img :src="images[name]"></img>
  </div>
  <p class="customer-text">
    {{ text }}
  </p>
</div>
</template>

<script>
import images from '../public/images/*.svg'

export default {
  props: ['name', 'text'],
  data() {
    return {
      images
    }
  }
}
</script>


今回は試しに文中にプログラムを含むような記事を書いてみたが、よくある文中のコードの埋め込みが無いので、 note でこういう記事は向かないかもしれない。

この記事が気に入ったらサポートをしてみませんか?