11

Using vue cli.

For some reason, SOME of my images, if I refer to them directly in the scss and don't bind them dynamically to my vue object have issues with relative paths.

Say I have a vue template with a div called box. Box has a background url of this:

.box{ background: url('../img/box.jpg')

That works locally just fine when I run npm run dev. But when I run build, it doesn't work. 404 error. I have also tried doing this:

.box{
background: url('~../img/box.jpg')

And that didn't work.

So there's this:

webpack css-loader not finding images within url() reference in an external stylesheet

And when I change this in webpack.config:

output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'build.js'
  },

To:

output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: './dist/',
    filename: 'build.js'
  },

It'll create Chunk Images in my webpack build with hashes for cacheing. And just for those specific images that aren't bound in the vue object.

And then I have to drag those images over to the root dist folder....rather than what I want to do which is keep them in an img folder relative to the html file ( html file is simply ):

<html lang="en">
  <head>

    <meta charset="utf-8">
    <title>vue</title>

  </head>
  <body>
    <script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>


    <app></app>
    <script src="dist/build.js"></script>
  </body>
</html>

Question is, do I have to bind every single vue img from the data...or can't I just directly refer to a image if I know it's not going to be changed.

Or is there some setting in my sass loader/webpack that i'm missing.

Here's my webpack config:

var path = require('path')
var webpack = require('webpack')

module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: './dist/',
    filename: 'build.js'
  },
  resolveLoader: {
    root: path.join(__dirname, 'node_modules'),
  },
  vue: {
    html: {
      root: path.resolve(__dirname, './dist')
    }
  },
  module: {
    loaders: [
      {
        test: /\.vue$/,
        loader: 'vue'
      },
      {
        test: /\.js$/,
        loader: 'babel',
        exclude: /node_modules/
      },
      {
        test: /\.json$/,
        loader: 'json'
      },
      {
        test: /\.html$/,
        loader: 'vue-html'
      },
      {
        test: /\.scss$/,
        loaders: ["style", "css", "sass"]
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'url',
        query: {
          limit: 10000,
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },
  devServer: {
    historyApiFallback: true,
    noInfo: true
  },
  devtool: '#eval-source-map'
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'
  // http://vue-loader.vuejs.org/en/workflow/production.html
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    }),
    new webpack.optimize.OccurenceOrderPlugin()
  ])
}

3 Answers 3

5

Try the url prefix of '~@/'

background-image: url('~@/assets/box.jpg');
Sign up to request clarification or add additional context in comments.

Comments

2

I managed to replicate your problem with the following steps:

Assuming the following directory:

root/
  dist/
  src/
    assets/
      |--box.jpg
    components/
      |--home.vue

And home.vue:

<template>
  <div class="foo">

  </div>
</template>

<script>
  export default {
  }
</script> 

<style>
  .foo {
    background: url('../assets/box.jpg')
  }
</style>

After building the application and save the files in the dist folder, everything works if I serve the built files using this command inside dist folder (I use lite-server for simplicity):

lite-server index.html

However, if I go back to the root folder and try to do the same:

lite-server dist/index.html

I will encounter the same problem as you.

How I usually get around this is by importing the image first and then using it with inline style:

<template>
  <div v-bind:style= "{ 'background-image': 'url(' + box + ')' }">
    Placeholder
  </div>
</template>

<script>
  // @ is an alias to /src
  import box from '@/assets/box.jpg';

  export default {
    data() {
      return { box };
    }
  }
</script>

Also check out the following discussions:

Comments

2

depends on where your root set, you could try background: url('~/assets/img/box.jpg') or background: url('~/src/assets/img/box.jpg'),
one of them should work

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.