1

My Vue.js web application is unable to find files with correct paths. I have checked the paths like 10 times, they are all correct and all give the 404 error. I tried relative path, absolute path and whatnot. There must be some Vue peculiarity which makes it unable to find the images.

The browser gives the following request summary (the path is given as '../assets/images/user.png'):

URL: http://localhost:8080/assets/images/user.png
Status: 404 Not Found
Source: Network
Address: 127.0.0.1:8080

A screenshot from VSCode:

enter image description here

MainPageBody.vue is the component that is supposed to show the images.
Been stuck at this for a while now.

Update: Followed @kissu's advice and used v-for, also created a brand new Vue project and copied my files there. However, the images are still throwing 404s. I must be doing something wrong. Tried using require(), that didn't help either.

The .json file on the URL may look something like:

{
    "posts": [
        {
            "author": "Samuel",
            "profilePicName": "../assets/images/user.png",
            "text": "Look at my dog!",
            "picName": "../assets/images/dog.jpg",
            "date": "29. Sept 2022"
        },

        {
            "author": "Bob",
            "profilePicName": "../assets/images/bob.jpg",
            "text": "Hello, I am Bob",
            "picName": "../assets/images/bob.jpg",
            "date": "7. Sept 2022"
        }
    ]
}

Reproducible example: I tried my best to make a reproducible example. I assume you still need to create a Vue project to reproduce my errors? If there is anything missing you need me to add, let me know.

<!-- MainPageBody.vue -->
<template>
    <div v-for="post in posts" :key="post.id"> 
        <!-- text comes through fine, image is not found -->
        <img :src="post.picName" />
        <p>{{ post.text }}</p>
    </div>
</template>

<script>
import { nanoid } from 'nanoid'

export default {

    data() {
        return {
            posts: null
        }
    },

    async created() {
        const response = await fetch('https://api.npoint.io/21b1db5b0e48a83466da') // working URL for json file
        const { posts } = await response.json()
        this.posts = posts.map((post) => {
            return { ...post, isHeld: false, id: nanoid() };
        })
    }
}
</script>
<!-- App.vue -->
<template>
    <MainPageBody/>
</template>

<script>
import MainPageBody from './components/MainPageBody.vue';

export default {
    name: 'App',
    components: {
    MainPageBody
    }
}
</script>

<style>
#app {
    font-family: Avenir, Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
    margin-top: 60px;
}
</style>

ahyes
  • 25
  • 6
  • How do you run your server? How do you import the asset in the code? Tried searching on the Internet how to load an image? Also, are you using Vue 2 or 3 (Webpack or Vite)? – kissu Dec 10 '22 at 22:22
  • @kissu Really not sure if my answers are sufficient, I don't know much about Vue. I run it by typing 'npm run serve' in the VSCode terminal. I import the assets using v-html and creating divs in script (I need to fetch the data from URL in .json format). The text added in script shows up fine, but the images give errors. I have searched extensively, but found no solutions that work for me. How do I find out which Vue version I am using? Sorry, I am very much a beginner. – ahyes Dec 10 '22 at 22:31
  • You're not supposed to use `v-html` as written in the documentation. Use `:src` binding with a regular `img` tag. If you need to fetch it with an HTTP call, having a `async/await` method populating an array or `computed` is the way to go. A text is not an actual import. The version you're using is written in `package.json` mainly. – kissu Dec 10 '22 at 22:35
  • @ahyes check this question pls : https://stackoverflow.com/questions/40491506/vue-js-dynamic-images-not-working – sadeq shahmoradi Dec 10 '22 at 22:36
  • try this `src="@/assets/images/user.png" ` too if you didn't set your images dynamic – sadeq shahmoradi Dec 10 '22 at 22:39
  • Okay, sorry, yes, I have Vue 3. I need to get both text and image source from the .json file. If I can't use the `v-html`, is there another way to but the image between text in every `div` if every `div` corresponds with an object in the .json file? Thank you for the first answer. – ahyes Dec 10 '22 at 22:41
  • @sadeqshahmoradi this is for dynamic images, may even not be needed here. Ask for the solution on how to load it with Vite, some code snippet or even a [repro] is quite welcome here. – kissu Dec 11 '22 at 00:03
  • @sadeqshahmoradi Vue3 comes with Vite by default. Webpack is quite an old bundler by today's standards. Waiting 60s for an HMR refresh seems quite old-school to me nowadays. – kissu Dec 11 '22 at 00:15
  • Hi, I've updated my answer regarding your latest update (HTTP call mainly). As for the images, if you have properly set up a brand new Vue3 project with the CLI as I've recommended in my other comments, you should have something working well. Now it's time to apply the 2nd line of my initial answer (for dynamic images with Vite). Of course, trying with some hardcoded ones + using the Vue devtools is always recommended if you want to debug efficiently. Otherwise, please edit your question with a [repro] so we can debug efficiently down the road! – kissu Dec 11 '22 at 17:05
  • @kissu is this example something you mean? – ahyes Dec 11 '22 at 17:48
  • Yeah, that endpoint will not be exposed to me so not really helping. Do you have something in your Vue devtools + network tab? What do you see in your DOM? Does it work with a hardcoded string? – kissu Dec 11 '22 at 17:49
  • [Link](https://drive.google.com/file/d/1UGKYDyaZvfRkf2E-Vjdr2F1raRbiyN5c/view?usp=share_link) to some screenshots because I didn't want to make this post too long. Also, yes, hardcoded strings do work for some reason. – – ahyes Dec 11 '22 at 18:16

1 Answers1

0

Those links may be helpful regarding how to load dynamic images with Vite.
Especially this answer with the 2022 answer: Vite 2.8.6 + Vue 3.2.31 part. The ./logo.png in there would be replaced by your dynamic profilePicName variable.

Otherwise, what you're doing in the lines below let out = '' is not something that you should do. Don't iterate on your object inside of a JS function like that. Instead, use a v-for and push each key of your object to the desired part. text can be wrapped in a {{ text }} while profilePicName goes to an :src.

Here is an example that I wrote recently that is using a (poorly designed) API with a basic v-for to iterate on all the keys of the object. Not directly a 1:1 to your case but could still be helpful IMO.


PS: if you could confirm us if you're using Webpack or Vite, that would be nice (can change the way dynamic images are imported with Webpack for example). Run your local dev server to find out (can post an image there afterwards).


Update

If you don't have a unique ID coming from the API you're using, you can always use nanoid. It's lightweight and will guarantee you no-collision regarding the uniqueness of your UUIDs. The guys maintaining the projects are good developers and super serious too.

Edit your objects with something like this

<template>
  <section>
    <div v-for="post in posts" :key="post.id">
      id: {{ post.id }} ~ author: {{ post.author }}
    </div>
  </section>
</template>

<script>
import { nanoid } from 'nanoid' // import it here

export default {
  data() {
    return {
      posts: [
        {
          id: nanoid(), // run it on each object
          author: 'Samuel',
          profilePicName: '../assets/images/user.png',
          text: 'Look at my dog!',
          picName: '../assets/images/dog.jpg',
          date: '29. Sept 2022',
        },
        {
          id: nanoid(),
          author: 'Bob',
          profilePicName: '../assets/images/user2.png',
          text: 'cool cat',
          picName: '../assets/images/cat.jpg',
          date: '13. Sept 2022',
        },
        {
          id: nanoid(),
          author: 'Sponge',
          profilePicName: '../assets/images/user3.png',
          text: 'cool fox',
          picName: '../assets/images/fox.jpg',
          date: '24 December 2022',
        },
      ],
    }
  },
}
</script>

You can of course initially first fetch your objects, then iterate on it with a .map, no need to have both at the same time.


Update

For your HTTP call, try something like this rather (you were not properly chaining with .then and .then is not recommended in comparison to async/await)

async created() {
  const response = await fetch('json_url_here')
  const { posts } = await response.json()
  this.posts = posts.map((post) => {
    return { ...post, isHeld: false, id: nanoid() }
  })
},
kissu
  • 40,416
  • 14
  • 65
  • 133
  • You have already helped me more than I could ever expect from a stranger, thank you, but the browser still throws 404s on the images. I am apparently using Webpack after all (got a 'webpack compiled with 3 errors' message when messing with the code). Tried the `v-for` thing, but still basically the same outcome. Text comes through from the json, images are not found. – ahyes Dec 11 '22 at 02:28
  • hold up a sec, I'll check out your edit – ahyes Dec 11 '22 at 02:29
  • @ahyes do you have a public GitHub repo by any luck? The fact that you do have Vue3 + Webpack is a strange configuration by itself. Is it a new project? Mind sharing a Github repo or at least a [repro]/more context regarding your issue so that I can reproduce and solve it on my side? Otherwise, don't worry: I'm doing that daily (helping strangers). :) – kissu Dec 11 '22 at 02:31
  • My current repo is a merge conflict hell, I'll create a new one from the folder and get back to you – ahyes Dec 11 '22 at 02:37
  • https://github.com/MiksMaSiinOlen/for-the-gentleman-on-stackoverflow.git took longer than I expected. The homework folder is really the thing I'm currently working on. – ahyes Dec 11 '22 at 03:08
  • @ahyes you still have some conflicts (`login.html`), also you have committed your `node_modules` (they should be git ignored), this is not at all a Vue project structure (any specific reason why you have not [used the CLI](https://vuejs.org/guide/quick-start.html#creating-a-vue-application)?), where are your `package.json`, bundler config files etc...? The `homework` directory is also totally empty. Give a read to the official documentation and follow the recommended structure! – kissu Dec 11 '22 at 03:14
  • okay yes something is wrong. It's not empty on my computer. I'll see what happened there, sorry. – ahyes Dec 11 '22 at 03:22
  • @ahyes please also consider the rest of my comment above. The structure itself seems to be quite wrong, mainly. – kissu Dec 11 '22 at 03:23
  • apparently my laptop ran out of space trying to copy the homework folder to the repo. sec. – ahyes Dec 11 '22 at 03:26
  • yes, I'll try to clean it up. – ahyes Dec 11 '22 at 03:26
  • @ahyes don't try to clean it up, start from scratch with a proper working setup thanks to the CLI. Then copy your files down there. Will be far better overall. – kissu Dec 11 '22 at 03:27
  • tbh I am not sure what I'm doing with this, but yes I added the homework folder. It itself should be like what a Vue project looks like? The reason the project as a whole is so messy is because I had previous homeworks without the use of Vue so I guess I kind of created a Vue project inside an already existing project. Probably not the most elegant of solutions I realise. If you want to give it a look, I will appreciate it, but if you're getting tired of solving my problems I understand haha. – ahyes Dec 11 '22 at 03:31
  • @ahyes I'm mainly telling you that your current setup is not good. Start from a fresh properly configured Vue3 CLI project and migrate your files down there. Will make you waste less time, trust me. Especially since now, you're using Vue and not vanilla JS. No issues with answering/giving more details, I would appreciate it if you take the time to read and follow the pieces of advice I give tho so that I don't feel like there is no interaction. – kissu Dec 11 '22 at 03:35
  • yes, I will create a new project – ahyes Dec 11 '22 at 03:36