3

I am using Laravel 5.8 and Vue 2.6 and trying to use a relative path for an image file in my single file component. I have reviewed the suggestions in How to import and use image in a Vue single file component? but cannot get it to work.

When trying:

<template>
  <div id="app">
    <img src="./assets/logo.png">
  </div>
</template>

<script>
export default {
}
</script>

<style lang="scss">
</style> 

I get this:

This relative module was not found: * ./assets/logo.png in ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib? ?vue-loader-options!./resources/js/components/xxxx.vue?vue&type=template&id=abd0e146&scoped=true&

When I try:

<template>
  <div id="app">
    <img :src="image" />
  </div>
</template>

<script>
import image from "./assets/logo.png"


export default {
    data: function () {
        return {
            image: image
        }
    }
}
</script>

<style lang="scss">
</style> 

I get:

This relative module was not found: * ./assets/logo.png in ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js /components/xxxx.vue?vue&type=script&lang=js&

Am I missing something with webpack-mix or vue-loader?

Edit:

Using simple static reference (src="/assets/logo.png") works on local development server, but doesn't on production server.

I've seen numerous suggested solutions for this basic image file referencing, but puzzled that there are so many possibilities and not a single best practice. Again, hoping to find a Best Practice when using Laravel/Laravel Mix/Vue and SFC that works in development and production.

mjpsr11
  • 595
  • 3
  • 10
  • 25

4 Answers4

3

There are 2 ways of using an image in your setup:

Bundled with webpack

<img src="./assets/logo.png">
import image from "./assets/logo.png" 

These bundle the image using webpack, and using this solution you get the benefits of:

  • Automatic inlinening with base64 for small images
  • Automatic "deep" compressing with any webpack loaders
  • Path works from every path in your app
  • Compile time checking if the file exists

Using your own webserver

const image = '/assets/logo.png'
const image = 'http://example.com/’

In these solutions, you need to setup your webserver yourself to serve those resources (or put them in the public directory)

  • Easy changing to a different image without rebuilding the front end
  • More flexible
Salim Djerbouh
  • 10,719
  • 6
  • 29
  • 61
Ferrybig
  • 18,194
  • 6
  • 57
  • 79
  • These don't work. Remember, I'm using Laravel framework with Laravel-mix. I suspect it may be why this prescribed method doesn't compile. – mjpsr11 Oct 14 '19 at 17:17
2

The answer to this is that the wrong deployment for the production server was being used that tried pointing to the 'public' folder instead of locating the public files on public_html.

After deploying according to this post, of course relative paths work exactly the same on development and production servers.

The only difference is in Step 5 for Laravel 5.8 in the server.php file,

Change

if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) {
    return false;
}

To

if ($uri !== '/' && file_exists(__DIR__.'/public_html'.$uri)) {
    return false;
}

Relative paths like

<img src="img/logo.png">

on either server work the same.

It's unfortunate that Laravel docs don't go into more detail on this method of deployment since I suspect there are numerous developers wanting to deploy on shared servers at least for testing purposes.

mjpsr11
  • 595
  • 3
  • 10
  • 25
1

Use

<img src="@/assets/logo.png">

This will use webpack and created a hashed version of your logo.png. Or in JS use:

:src="require('@/assets/logo.png');
Saa
  • 1,540
  • 10
  • 22
  • 1
    That gives me this error: "This dependency was not found: * @/assets/logo.png in ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib? ?vue-loader-options!./resources/js/components/xxxx.vue?vue&type=template&id=abd0e146&scoped=true& – mjpsr11 Oct 14 '19 at 16:00
  • Are you absolutely sure that your logo is in the correct path? should be in resources/assets/logo.png – Saa Oct 14 '19 at 19:56
  • Thanks, I moved the file into the resources/assets folder. Unfortunately, same result. You said that using the img tag will use webpack to create a hashed version of the png. Do I need to tell webpack to look in the resources folder for assets or does the '@' prefix do that? – mjpsr11 Oct 14 '19 at 21:45
  • BTW, all references I've seen say to put image files in the public/ folder, not the resources/ folder for Laravel and Larevel Mix. – mjpsr11 Oct 14 '19 at 21:54
1

Provided that your image is stored in public folder and is accessible, you can link to it by absolute path just fine instead of using a relative path ./

<template>
    <div id="app">
        <img src="/public/img/widgets/logo.png" />
    </div>
</template>

<script>
export default {};
</script>

<style lang="scss">
</style>

Given you have this structure

enter image description here

Hope this helps

Salim Djerbouh
  • 10,719
  • 6
  • 29
  • 61
  • Doesn't work. Compiles ok, but cannot resolve path. Actually, src="/asset/logo.png" works on development server, but not production server. I'm still searching for best practice with Laravel/Vue. – mjpsr11 Oct 14 '19 at 17:19
  • There's no "path resolution" here, the HTML is output as it is and even if the image doesn't exist at all or the path is completely incorrect, it would still compile, make sure the image is actually on that route, or give me the URL of the image on the server and I will create a sandbox with a vue component correctly showing it – Salim Djerbouh Oct 14 '19 at 17:23
  • As stated, this compiles okay and the image does display for src="/asset/logo.png". – mjpsr11 Oct 14 '19 at 17:54