15

Could you explain me how to access assets from webpacker gem within vue.js components? For example - how to create div with background image. I've tried use /app/assets/images and /app/javascripts/assets folders but images is only available in template section, but not in style section :(

in my case

<template>
    <div id="home">
        <div id="intro">
            <img src="assets/cover-image-medium.png" alt="">
        </div>
    </div>
</template>

works fine, but

<style scoped>
    #intro {
        height: 200px;
        background: url("assets/cover-image-medium.png");
    }
</style>

not working :(

Whats wrong?

Alexey Poimtsev
  • 2,845
  • 3
  • 35
  • 63

5 Answers5

14

New Rails' webpacker stuff is pretty raw, so that's the configuration that works for me:

config/webpacker.yml (for webpacker 3):

resolved_paths: ['app/javascript/images', 'app/javascript/src']
compile: false
# ...

JS files:

/app
  /javascript
    /packs
      # only entry point files
      vue_application.js
    /src
      some_component.vue
    /images
      logo.svg

in component:

<script>
import 'images/logo.svg'
</script>

in template:

<img src='~images/logo.svg' />

point the tilde here - it means that the image is a module dependency

in CSS:

<style lang='sass'>
#app
  background: url('../images/logo.svg')
</style>

For some reason tilde does not work here, so relative path is used.

sandrew
  • 3,109
  • 5
  • 19
  • 29
  • Thank you @sandrew, your answer was really helpful – hedin Nov 20 '17 at 03:22
  • If I use `` and `pathFromComputedProp(){ return '~images/logo.svg' }` - this will not work. Also, it will not work if instead tilde I will use relative path: `pathFromComputedProp(){ return '../images/logo.svg' }`. Maybe there is way to fix it too? – hedin Nov 21 '17 at 17:12
  • Thank you! (Why is this NOT in the webpacker documentation!?) – tgf Mar 27 '18 at 22:25
5

If I understand your question correctly, you will have to find the webpack.base.conf.js file inside your build folder, then find the code that looks like this:

resolve: {
  extensions: ['.js', '.vue', '.json'],
  alias: {
    'vue$': 'vue/dist/vue.esm.js',
    '@': resolve('src')
  }
}

Then add the following line to the alias object: 'assets': resolve('src/assets/'), which will work for the assets folder being right below the src folder. You can also change the key string from assets to whatever alias name you desire.

EDIT:

I forgot to mention, to access aliases in style code, you have to prefix it with a ~ (telda) so that assets becomes ~assets.

Rashad Saleh
  • 2,686
  • 1
  • 23
  • 28
3

Since this is tagged with Vue.js I will answer for that. None of the other answers worked with Vue 2.x.

For Attributes

A webpacker require statement returns the full URL of the required asset (resolved based on your resolved_paths inside webpacker.yml). Based on that, you can do something like this:

<img :src="require('images/what-a-pain.png')" alt="Finally working" />

Please note the colon causing the src attribute to be bound to the result of the javascript expression.

You can also use ID anchors by appending them, for example with SVG:

<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
    <use :href="require('images/icons.svg') + '#copy'" />
</svg>

Vue templates are generally pre-compiled to javascript equivalents, so a require statement is needed to pull the assets in at compile time, not runtime.

For CSS urls, scoped or not

Simply use a tilde ~ and a path. The path must be relative to either the file including it or the resolved_paths from webpacker.yml.

.relative-pathed {
    background: url(~../../../assets/images/quitethepath.svg) center center no-repeat;
}
.works-after-editing-webpackeryml {
    background: url(~images/quitethepath.svg) center center no-repeat;
}

For this usage there is no need to require() the asset.

Please note: there is a difference in paths between development and production, especially if Sprockets is also used. Simply doing src="/assets/image.png" will sometimes work in developement, but not production.

adc
  • 557
  • 4
  • 13
1

You can try

background: url("/assets/cover-image-medium.png");  

Instead of

background: url("assets/cover-image-medium.png");
TomServo
  • 7,248
  • 5
  • 30
  • 47
artgb
  • 3,177
  • 6
  • 19
  • 36
  • Doesn't work - Failed to load resource: the server responded with a status of 404 (Not Found) – Alexey Poimtsev Aug 14 '17 at 09:01
  • I did changes in development.rb related to static assets from this link, but still don't work. Here is log - https://pastebin.com/W1v73fLj As you may see - webpack is failed to compile – Alexey Poimtsev Aug 14 '17 at 10:15
0

If you have installed sass-rails gem, try this:

<style scoped>
#intro {
    height: 200px;
    background: image-url("cover-image-medium.png");
}
</style>
Cong Chen
  • 2,436
  • 12
  • 21