Ad

Images In Vue-cli Causing Issues. Node- Express, Mysql Backend

- 1 answer

I have some code that uploads images to a folder on my server and stores a reference in a mysql database. All was fine in development, but trying to work with production my images are undefined and 404 error results.

I found the documentation, VUE Static Files But I am struggling with this setup, as I have another server set up as an NGINX proxy server, so all my traffic goes there first. I have tried using relative paths. Storing the full path in my database, just the file name, and trying to work that into my server and build for production. For example I am trying to figure out how to use assets to house image files that will be there when uploaded from the back-end.

If I just focus on the frontend, my backend server has uploaded an image file to this the /dist/img/ folder and I wand to reference that in the frontend vue files.


<template>
    <div class="ui link cards">
        <div class="card" id="custom-card">
            <div class="ui header">Today's Feed</div>
            <button class="ui button" id="sub-button" @click="showTodaysItems">Submit</button>
            <button class="ui button" @click="clearReport">Clear</button>
        </div>

            <hr>
            <div class="ui container response-modal modal"  id="report-modal" v-if="reportData.length >= 1">
                <div class="ui header">Todays Items</div>
                <i id="close-icon" class="big close icon right top" @click.prevent="onClose"></i>
                <div class="ui  devided items">
                    <div class="item" id="report-item" v-for="(item, index) in reportData" :key="`item-${index}`"  @click="showItem(item)" >
                        <div>
                        {{item.description}}
                        </div>
                        <div>
                        {{item.notes}}
                        </div>
                        <div>
                        {{item.commodity}}
                        </div>
                        <div>
                        {{item.sampleDate}}
                        </div>
                        <div>
                        {{item.carrier}}
                        </div>
                        <div>
                        {{item.shipper}}
                        </div>
                         <div v-if="item.approve == 1">
                            Approved
                        </div>
                        <div v-else>
                            Rejected
                        </div>
                        <img class="ui tiny image" :src="getImageUrl(item.image)">
                    </div>

                </div>

            </div>
    </div>
</template>

<script>
    const API_REPORTS_ENDPOINT = "localhost/api/reports/";
    import axios from 'axios';
    const todaysDate = new Date();
    let dd = String(todaysDate.getDate()).padStart(2, '0');
    let mm = String(todaysDate.getMonth() + 1).padStart(2, '0');
    let yyyy = todaysDate.getFullYear();
    var todayFormatedDate = yyyy + "-" + mm + "-" + dd;
export default {
    data() {
        return {
            today: {
                todaysDate: todayFormatedDate,
            }, 
            reportData: [],
            showSelectedTodaysItems: false,
            selectedItem: {},
        }
    },
    name: 'reports',
    methods: {
        showTodaysItems(event) {
            axios.post(API_REPORTS_ENDPOINT + 'todaysFeed',
                    this.today,
                    { headers: {
                        'Content-type' : 'application/json',
                    }
                    }).then(response => {
                        this.reportData = response.data.data;
                }).catch(error => {console.log(error)}); 
        },
        showItem(i) {
            this.selectedItem = i;
            this.showSelectedTodaysItems = true;
        },
        closeTodaysItems() {
            this.selectedItem = {};
            this.showSelectedTodaysItems = false;
        },
        clearReport() {
            this.reportData = {};
        },
        onClose() {
            this.reportData = {};
            this.showSelectedRangeItems = false;
        },
        getImageUrl(image) {
            return require('../../../public/images/'+ image)
        }
    },
}
</script>

My issue is where I am requiring the image file worked in development, but everything got minified and moved around for production, I don't fully understand how to fix this based on the docs, I have tried, using '/assets/' like that, using base url, but it's not making much sense, could there be an easier way to handle this.

Ad

Answer

If your images are in the public directory, you don't need require, you can reference them directly since everything in the public directory is bundled as-is.

For example, add the BASE_URL to your data properties...

data() {
  return {
    publicPath: process.env.BASE_URL,
    // etc
  }
}

and in your template

<img class="ui tiny image" :src="`${publicPath}images/${item.image}`">

See https://cli.vuejs.org/guide/html-and-static-assets.html#the-public-folder


FYI, having method calls like getImageUrl() in your templates is very inefficient and should be avoided where possible.

Ad
source: stackoverflow.com
Ad