Published on

Handling Dynamic Image Src in Vue 3 with Vite

Authors
  • Name
    Ripal & Zalak
    Twitter

How to Set Dynamic Image Src in Vue 3 with Vite

The Problem

Dynamic image paths in Vue 3 with Vite can cause issues after production builds. While static image sources work seamlessly, dynamically generated paths may not function correctly, often leading to 404 Not Found errors.

<!-- Static image - Works in both dev and production -->
<img src="/src/assets/images/static-image.png" alt="Static Image" />

<!-- Dynamic image - Works only in dev mode -->
<img :src="'/src/assets/images/' + dynamicImage" alt="Dynamic Image" />

The issue arises because Vite rewrites and optimizes paths during production, but dynamically constructed paths aren't processed the same way.


Solutions

1. Use import.meta.url

Leverage new URL with import.meta.url to construct dynamic paths. This method ensures paths are resolved correctly in both development and production.

<template>
  <img :src="imageSrc" alt="Dynamic Image" />
</template>

<script setup>
const imageSrc = new URL(`../assets/images/${dynamicImageName}`, import.meta.url).href
</script>

2. Use import.meta.glob

Vite provides import.meta.glob to import multiple files dynamically. This method is suitable for cases where you need a dynamic list of images.

<template>
  <img :src="images[`/src/assets/images/${imageName}`]?.default" alt="Dynamic Image" />
</template>

<script setup>
const images = import.meta.glob('/src/assets/images/*', { eager: true })
const imageName = 'example.png'
</script>

3. Store Images in public Folder

For simple use cases, store images in the public folder. Paths from the public folder are served as-is and aren't processed by Vite.

<template>
  <img :src="`/images/${dynamicImageName}`" alt="Dynamic Image" />
</template>

Place images in public/images/ and reference them directly.

4. Computed Property for Dynamic Paths

Use a computed property to dynamically construct image URLs based on conditions.

<template>
  <img :src="computedImageUrl" alt="Dynamic Image" />
</template>

<script setup>
import { computed } from 'vue'

const dynamicCondition = true
const computedImageUrl = computed(() => {
  return new URL(dynamicCondition ? './image1.png' : './image2.png', import.meta.url).href
})
</script>

FAQs

Why does this issue occur in Vite?

Vite optimizes and rewrites static assets during production builds. Dynamic paths aren't analyzed or rewritten, leading to broken links.

Can I use require for dynamic imports?

require is not supported in Vite. Use import.meta.url or import.meta.glob for dynamic imports.

When should I use the public folder?

Use the public folder for assets that don’t require optimization or bundling by Vite, such as large static files or dynamically referenced images.