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> 

require is not define error

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 require in 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 } } 
2

In 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.

1

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> 

demo

1

for 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.

see also:

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

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.