I switched from the Vue CLI to Vite CLI, and from the Composition API of Vue 3 to SFC Script setup API.
How it previously worked for me
When I was using the official Vue CLI, I could import an image source by passing the filename of the path by the props :
<template> <img :src="require(`@/assets/${imagePath}`)"/> <template/> <script> export default { props: { imagePath: { type: String }, }, setup() { // ... } } <script/> And then call it like this :
<template> <Image imagePath="icon.png" /> </template> The error I get since I migrated to Vite
But since I migrated to the Vite CLI, I have an error "Uncaught ReferenceError: require is not defined". My file now use the script setup syntax and looks like this :
<script setup> const props = defineProps({ imagePath: { type: String }, }) </script> <template> <img :src="require(`@/assets/${props.imagePath}`)"/> </template> What I tried
I already tried to import the file directly from the assets folder with a relative path, and it worked. But I cannot specify the path from props with the import statement.
<script setup> // Works but do not use the props, so the component is not reusable import logo from "./../assets/logo.png" </script> <template> <img :src="logo"/> </template> <script setup> // Component is reusable but the import statement has illegal argument I guess const props = defineProps({ imagePath: { type: String }, }) import logo from `./../assets/${props.imagePath}` </script> <template> <img :src="logo"/> </template> I also tried the import statement in the template but it cannot even compile the code :
<script setup> const props = defineProps({ imagePath: { type: String }, }) </script> <template> <img :src="import `./../assets/${props.iconPath}`" /> </template> Am I missing something ? Maybe a plugin exists and can help me achieve this ?
5 Answers
I also encountered this problem. I searched about this and found according to this github issue comment,
There should never be
requirein source code when using Vite. It's ESM only.
More about this on Features | Vite - Static Assets
A bit of searching lead me to this Vue 3 code sample link that worked for me
<CarouselItem v-for="(item,index) of carouselData" :key="index"> <img :src="getImageUrl(item.img_name)" /> </CarouselItem> setup() { const getImageUrl = (name) => { return new URL(`../../lib/Carousel/assets/${name}`, import.meta.url).href } return { carouselData, getImageUrl } } 2In case you're using require.context, the new way seems to be glob import. Change your old statement from:
const locales = require.context("../../lang", true, /[A-Za-z0-9-_,\s]+\.json$/i) to:
const locales = import.meta.glob('../../lang/*.json') Edit:
This also seems to replace require.
Use a watcher on the imagePath prop that dynamically imports the image, and updates a ref (bound to the <img>.src) with the result:
<script setup> import { ref, watchEffect } from 'vue' const props = defineProps({ imagePath: { type: String }, }) const logo = ref() watchEffect(async () => { logo.value = (await import(/* @vite-ignore */ `../assets/${props.imagePath}`)).default }) </script> <template> <img :src="logo"> </template> 1for those who will use static assets with vue + vite, they can use this method.
import imgUrl from '../../img/bgimg.jpg' export default { data() { return { bgImage: imgUrl }; }, }; then you can use it like this
<div :style="{ backgroundImage: 'url(' + bgImage + ')', }" ></div> Importing a static asset will return the resolved public URL when it is served:
import imgUrl from './img.png' document.getElementById('hero-img').src = imgUrl For example, imgUrl will be /img.png during development, and become /assets/img.2d8efhg.png in the production build.
If none of provided answers is not help (as in my case) - try to use <slot/> instead, as shown below:
//card component (child) <template> <div> <slot /> </div> </template> //services component (parent) <template> <ServiceCard> <img src="@/assets/icons/service-1.svg" alt="svg image" /> </ServiceCard> <ServiceCard> <img src="@/assets/icons/service-2.svg" alt="svg image" /> </ServiceCard> </template> 1
