Comprehensive Guide to Image Management in Vue 3 + Vite Projects
This article explains how to organize, import, dynamically load, batch import, and lazily load images in Vue 3 + Vite applications, covering static assets, CSS references, template usage, URL handling, import.meta.glob, and common pitfalls with path aliases.
In Vue 3 + Vite projects, managing images efficiently improves performance and developer experience. Images are typically stored in two directories: src/assets for assets that need Vite processing (supporting dynamic imports and alias @) and public for static resources that are served directly.
Static Image Loading
Template Import from src/assets
<template>
<img src="@/assets/a.jpg" alt="Static Image" />
</template>Template Import from public
<template>
<img src="/vite.svg" alt="Public Image" />
</template>Relative Path Import
<template>
<img src="../assets/b.jpg" alt="Relative Image" />
</template>CSS Background Image
.background {
background-image: url('@/assets/a.jpg');
} .background {
background-image: url('/vite.svg');
} .background {
background-image: url('../assets/b.jpg');
}Dynamic Image Loading
Why Use Dynamic Loading
Dynamic loading is needed when image paths are generated from data at runtime.
<template>
<div class="wrap">
<img :src="imagePath" />
</div>
</template>
<script setup>
import { ref } from 'vue'
const name = "c.jpg"
const imagePath = `@/assets/${name}`
</script>This approach fails because the @ alias is not resolved inside template strings. The alias works only with import statements or Vite’s dynamic import APIs.
Using new URL (no variables)
<template>
<img :src="imagePath" alt="Static Image" />
</template>
<script setup>
const imagePath = new URL('@/assets/c.jpg', import.meta.url).href;
console.log(imagePath);
</script>Variables cannot be used directly with new URL because the alias is resolved only at build time.
Dynamic Loading with Variables
Several alternatives exist:
Use a relative path:
const name = "c.jpg";
const imagePath = new URL(`../assets/${name}`, import.meta.url).href;Use import.meta.glob for batch imports:
const images = import.meta.glob('@/assets/*.jpg', { eager: true });
const name = "c.jpg";
const imagePath = images[`/src/assets/${name}`]?.default;Avoid the alias and build the path manually:
const name = "c.jpg";
const imagePath = new URL(`src/assets/${name}`, import.meta.url).href;Looping Over Images
When iterating with v-for, the alias is treated as a plain string and does not resolve:
<template>
<div v-for="name in imageNames" :key="name">
<img :src="getImagePath(name)" :alt="name" />
</div>
</template>
<script setup>
const imageNames = ['b.jpg', 'c.jpg', 'd.jpg'];
const getImagePath = (fileName) => {
return new URL(`@/assets/${fileName}`, import.meta.url).href;
};
</script>Solutions include using relative paths, placing images in public, or pre‑building an array of resolved URLs.
Batch Dynamic Import with import.meta.glob
import.meta.globscans a directory and returns a mapping of file paths to import functions (or the imported module when eager: true is set).
const images = import.meta.glob('@/assets/*.jpg', { eager: true });
for (const [key, value] of Object.entries(images)) {
const fileName = key.split('/').pop();
// value.default contains the image URL
}Advanced usage can filter files with patterns, e.g., gcshi_*.jpg:
const imageFiles = import.meta.glob('@/assets/images/gcshi_*.jpg');Lazy Loading Images
To improve first‑paint performance, integrate a lazy‑load library such as vanilla‑lazyload:
<template>
<div v-for="(src, name) in images" :key="name" class="image-container">
<img :data-src="src" :alt="name" class="lazy" />
</div>
</template>
<script setup>
import LazyLoad from 'vanilla-lazyload';
const imageFiles = import.meta.glob('@/assets/images/*.jpg');
const images = {};
for (const [key, value] of Object.entries(imageFiles)) {
images[key.split('/').pop()] = await value();
}
onMounted(() => {
new LazyLoad({ elements_selector: '.lazy' });
});
</script>Common Issues and Fixes
Path Alias Not Working
Ensure the alias is correctly defined in vite.config.js:
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { resolve } from 'path';
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
"@": resolve(__dirname, "src"), // maps @ to src directory
},
},
});Incorrect CSS Paths After Build
Use absolute paths referencing the public folder or Vite’s alias for assets located in src/assets.
Conclusion
By applying the techniques above—static imports, new URL for dynamic paths, import.meta.glob for batch imports, and lazy‑load integration—developers can manage images in Vue 3 + Vite projects more efficiently and reliably.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
