How to reference static assets within vue javascript
Asked Answered
R

14

176

I'm looking for the right url to reference static assets, like images within Vue javascript.

For example, I'm creating a leaflet marker using a custom icon image, and I've tried several urls, but they all return a 404 (Not Found):

Main.vue:

var icon = L.icon({
    iconUrl: './assets/img.png',
    iconSize:     [25, 25],
    iconAnchor:   [12, 12]
});

I've tried putting the images in the assets folder and the static folder with no luck. Do I have to tell vue to load those images somehow?

Redundancy answered 15/11, 2017 at 16:57 Comment(1)
webpack? That usually wants to know if an image is included so it gets put in the bundle. OTher bundling systems probably don't care, as long as the image gets deployed to your serverPreconize
W
272

For anyone looking to refer images from template, You can refer images directly using '@'

Example:

<img src="@/assets/images/home.png"/>
Weighty answered 24/5, 2018 at 17:55 Comment(11)
... given you have a folder src/assets/images. Out of the box, vue-loader copies assets from src/../... to build/../.. OR inlines smaller pictures as data.image/png.. automatically.Duress
did not work for me: This dependency was not found:* @/assets/more-ico.svg. To install it, you can run: npm install --save @/assets/more-ico.svg...Specific
Did not work for me either, but..... i saw then that i used the wrong filename ;p works perfectly!Rriocard
It works, but on template, if you want to use in css background-img property, try something like ../../assets/bg/login.svg, with the image into the assets folderWhitworth
Thank you. The vue documentation on static assets is needlessly verbose and buries this primary usecase nearly at the bottom of the page, in a tiny bullet point.Twerp
does not answer the question.Benyamin
Module not found: Error: Can't resolve . I'm getting this errorAnagnos
this solution was not perfect for some vue js application. Instead of that, I created prop and assign the image location. <img :src="url" /> return { data: { url: "images/image.png" } }Anagnos
Worked perfectly for me!Perce
This didn't work for me using a vite electron setup. I had to use the relative path from a component in src/components which was ../assets/image.png.Proffer
As for today (in case someone uses Vue 3 & Vite), this is still true, however you must define an alias for @ as follows (in vite.config.js): resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } }, and don't forget to import { fileURLToPath, URL } from 'node:url' above.Pyongyang
S
115

In a Vue regular setup, /assets is not served.

The images become src="data:image/png;base64,iVBORw0K...YII=" strings, instead.


Using from within JavaScript: require()

To get the images from JS code, use require('../assets.myImage.png'). The path must be relative (see below).

So your code would be:

var icon = L.icon({
    iconUrl: require('./assets/img.png'),   // was iconUrl: './assets/img.png',
//  iconUrl: require('@/assets/img.png'), // use @ as alternative, depending on the path
    // ...
});

Use relative path

For example, say you have the following folder structure:

- src
  +- assets
     - myImage.png
  +- components
     - MyComponent.vue

If you want to reference the image in MyComponent.vue, the path sould be ../assets/myImage.png


Here's a DEMO CODESANDBOX showing it in action.

Singletree answered 3/3, 2018 at 3:3 Comment(2)
After scaffolding my app with vue-cli, this technique worked for me. The code sandbox was very helpful. The answer isn't as clear as the code sandbox.Flynt
require('./assets/img.png') didn't work for me in my component's options, I had to replace the . with a @: require('@/assets/img.png').Daddylonglegs
S
44

A better solution would be

Adding some good practices and safity to @acdcjunior's answer, to use @ instead of ./

In JavaScript

require("@/assets/images/user-img-placeholder.png")

In JSX Template

<img src="@/assets/images/user-img-placeholder.png"/>

using @ points to the src directory.

using ~ points to the project root, which makes it easier to access the node_modules and other root level resources

Scoliosis answered 8/10, 2019 at 14:14 Comment(2)
What if its not an image but rather a text file or csv? And just want to get the path/url ?Rhoda
@trainoasis, you can use <a href="..."> for files of other type.Tumescent
E
26

In order for Webpack to return the correct asset paths, you need to use require('./relative/path/to/file.jpg'), which will get processed by file-loader and returns the resolved URL.

computed: {
  iconUrl () {
    return require('./assets/img.png')
    // The path could be '../assets/img.png', etc., which depends on where your vue file is
  }
}

See VueJS templates - Handling Static Assets

Earthwork answered 11/3, 2018 at 20:56 Comment(0)
C
18

Right after oppening script tag just add import someImage from '../assets/someImage.png' and use it for an icon url iconUrl: someImage

Chrischrism answered 15/11, 2018 at 8:38 Comment(2)
This worked well for me when incorporating the '@' in the import.Renfrew
What about dynamic images?Someway
E
17

this finally worked for me, image passed as prop:

<img :src="require(`../../assets/${image}.svg`)">
El answered 30/12, 2020 at 1:45 Comment(2)
Or using "@": <img :src="require(`@/assets/${image}.svg`)">Coelho
In my case i used require(../assets/country-flags-main/...svg)Someway
S
2

What system are you using? Webpack? Vue-loader?

I'll only brainstorming here...

Because .png is not a JavaScript file, you will need to configure Webpack to use file-loader or url-loader to handle them. The project scaffolded with vue-cli has also configured this for you.

You can take a look at webpack.conf.js in order to see if it's well configured like

...
    {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
...

/assets is for files that are handles by webpack during bundling - for that, they have to be referenced somewhere in your javascript code.

Other assets can be put in /static, the content of this folder will be copied to /dist later as-is.

I recommend you to try to change:

iconUrl: './assets/img.png'

to

iconUrl: './dist/img.png'

You can read the official documentation here: https://vue-loader.vuejs.org/en/configurations/asset-url.html

Hope it helps to you!

Stenograph answered 15/11, 2017 at 17:53 Comment(1)
I'm not sure what system I'm using, or if I have to add it manually. I tried the ./dist url and no luckRedundancy
L
1

It works for me by using require syntax like this:

$('.eventSlick').slick({
    dots: true,
    slidesToShow: 3,
    slidesToScroll: 1,
    autoplay: false,
    autoplaySpeed: 2000,
    arrows: true,
    draggable: false,
    prevArrow: '<button type="button" data-role="none" class="slick-prev"><img src="' + require("@/assets/img/icon/Arrow_Left.svg")+'"></button>',
Lascivious answered 4/2, 2021 at 7:32 Comment(0)
W
1

You could define the assets path depending on your environment

const dev = process.env.NODE_ENV != 'production';
const url = 'https://your-site.com';
const assets = dev ? '' : url;
<template>
    <img :src="`${assets}/logo.png`"/>
    <p>path: {{assets}}</p>
</template>
<script>
    export default {
        data: () => ({
            assets
        })
    }
</script>

Ideally this would be inside an utils js file, or as an extended app defineProperty, like:

const app = createApp(component);
app.config.globalProperties.$assets = assets;
app.mount(element);

and will be available as:

<template>
    <img :src="`${$assets}/logo.png`"/>
    <p>path: {{$assets}}</p>
</template>
<script>
    export default {
        mounted() {
            console.log(this.$assets);
        }
    }
</script>
Woodenware answered 16/1, 2022 at 12:2 Comment(0)
U
1

For anyone coming here looking for a more modern JS answer, you need to import the image for the bundler (either Vite or Webpack) to pick it up. The following solution works when running in both dev and production modes:

import iconUrl from '@/assets/img.png';

const icon = L.icon({
    iconUrl:      iconUrl,
    iconSize:     [25, 25],
    iconAnchor:   [12, 12]
});
Unbodied answered 19/6, 2023 at 18:50 Comment(0)
F
0

Having a default structure of folders generated by Vue CLI such as src/assets you can place your image there and refer this from HTML as follows <img src="../src/assets/img/logo.png"> as well (works automatically without any changes on deployment too).

Farce answered 12/11, 2019 at 9:1 Comment(0)
M
0

I'm using typescript with vue, but this is how I went about it

<template><div><img :src="MyImage" /></div></template>
<script lang="ts">
    import { Vue } from 'vue-property-decorator';
    export default class MyPage extends Vue {
            MyImage = "../assets/images/myImage.png";
        }
</script>
Meandrous answered 9/3, 2020 at 16:10 Comment(0)
L
0

load them in created, mounted or where you need them

async created() {
   try {
      this.icon = (await import('@assets/images/img.png')).default;
   } catch (e) {
      // explicitly ignored
   }

and then

<img :src=icon />
Lulu answered 22/2, 2022 at 23:4 Comment(0)
H
0

Inside code you can directly require image using.

const src = require("../../assets/images/xyz.png");

Or

In order to dynamically load image need this.

const image = new window.Image();
image.src = require("../../assets/images/xyz.png");
image.onload = () => {
// do something if needed
 };
Hexose answered 11/4, 2022 at 10:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.