0

I'm having trouble trying to get the browser to successfully find a background image whilst using webpack and sass-loader/style-loader/css-loader.

The path seems to be right, because whenever I change it the compile process fails, but as it is, it is ok.

So far I have...

Component

import React from 'react'

const Image = () => (
   <div className='sprite-container sprite-1'>
   </div>
)

export default Image

CSS

.sprite-container {
   width: 100px;
   height: 100px;
   border-radius: 100%;
   border: 1px solid blue; // I put this just to confirm the container div is there, which it is.
   background-image: url('/img/spritesheet.png');
   background-repeat: no-repeat;
   position: absolute;
   top: 250px;
   right: 20px;
}

.sprite-1 {
   background-position: -100px, -100px;
}

As it is, the div is transparent. The container is there but the background image fails to load. I'm new to compiling SASS in Webpack, so maybe this is something to do with my file structure.

This is the relevant part of my file tree:

- src
   - static (all static assets are served from this folder)
      - img
         -- spritesheet.png
   - styles
         -- app.scss
   -- app-client.js (importing app.scss here)

I'm importing the app.scss into my main js file, app-client.js (which React mounts to the application).

Does the path given in the background-image css property need to be relative the root directory or the stylesheet? I'm assuming the root directory (/static).

Any help appreciated.


UPDATE

File tree

- src
   - static (all static assets are served from this folder)
      - img
         -- spritesheet.png
      - js
         -- bundle.js
   - styles
         -- app.scss
   -- app-client.js (importing app.scss here)

webpack.config.js

const debug = process.env.NODE_ENV !== "production";

const webpack = require('webpack');
const path = require('path');

// const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  devtool: debug ? 'inline-sourcemap' : null,
  entry: path.join(__dirname, 'src', 'app-client.js'),
  devServer: {
    inline: true,
    port: 3333,
    contentBase: "src/static/",
    historyApiFallback: {
      index: '/index-static.html'
    }
  },
  output: {
    path: path.join(__dirname, 'src', 'static', 'js'),
    publicPath: "/js/",
    filename: 'bundle.js'
  },
  module: {
    loaders: [
      {
         test: path.join(__dirname, 'src'),
         loader: ['babel-loader'],
         query: {
            cacheDirectory: 'babel_cache',
            presets: debug ? ['react', 'es2015', 'react-hmre'] : ['react', 'es2015']
         }
      },
      {
         test: /\.scss$/,
         loaders: [ 'style', 'css?sourceMap', 'sass?sourceMap' ]
         // loader: ExtractTextPlugin.extract(
         //     'style', // The backup style loader
         //     'css?sourceMap!sass?sourceMap'
         // )
      },
      {
         test: /\.png$/,
         loader: "url-loader?limit=10000&minetype=image/jpg"
      }
    ]
  },
  plugins: debug ? [] : [
   //  new ExtractTextPlugin('styles.css'),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
    }),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: { warnings: false },
      mangle: true,
      sourcemap: false,
      beautify: false,
      dead_code: true
    }),
  ]
};

package.json

{
  "name": "***",
  "version": "1.0.0",
  "description": "***",
  "main": "src/server.js",
  "repository": "**REPO**",
  "scripts": {
    "start": "NODE_ENV=production node_modules/.bin/babel-node --presets 'react,es2015' src/server.js",
    "start-dev": "npm run start-dev-hmr",
    "start-dev-single-page": "node_modules/.bin/http-server src/static",
    "start-dev-hmr": "node_modules/.bin/webpack-dev-server --progress --inline --hot",
    "build": "NODE_ENV=production node_modules/.bin/webpack -p"
  },
  "author": "***",
  "license": "UNLICENSED",
  "dependencies": {
    "axios": "^0.15.3",
    "babel-cli": "^6.11.4",
    "babel-core": "^6.13.2",
    "babel-loader": "^6.2.5",
    "babel-plugin-react-html-attrs": "^2.0.0",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-plugin-transform-object-rest-spread": "^6.22.0",
    "babel-preset-es2015": "^6.13.2",
    "babel-preset-react": "^6.11.1",
    "babel-preset-react-hmre": "^1.1.1",
    "babel-preset-stage-2": "^6.22.0",
    "ejs": "^2.5.1",
    "express": "^4.14.0",
    "react": "^15.3.1",
    "react-dom": "^15.3.1",
    "react-redux": "^5.0.2",
    "react-router": "^2.6.1",
    "redux": "^3.6.0",
    "redux-logger": "^2.7.4",
    "redux-thunk": "^2.2.0"
  },
  "devDependencies": {
    "css-loader": "^0.26.1",
    "file-loader": "^0.9.0",
    "http-server": "^0.9.0",
    "node-sass": "^4.3.0",
    "react-hot-loader": "^1.3.0",
    "sass-loader": "^4.1.1",
    "style-loader": "^0.13.1",
    "url-loader": "^0.5.7",
    "webpack": "^1.13.2",
    "webpack-dev-server": "^1.14.1"
  }
}
Paulos3000
  • 3,355
  • 10
  • 35
  • 68
  • Since your image URL starts with a slash, it's absolute, so you need to specify it as `'/static/img/spritesheet.png'` – Tudor Ilisoi Jan 21 '17 at 18:42
  • @TudorIlisoi - tried that... still no joy :( – Paulos3000 Jan 21 '17 at 18:44
  • did you also try `'../img/spritesheet.png' ` ? – Tudor Ilisoi Jan 21 '17 at 18:45
  • Yep, that just causes the compile process to fail as the filepath doesn't exist. Adding `../` removes `/static` from the filepath – Paulos3000 Jan 21 '17 at 18:47
  • well, maybe this answer sheds some light? It also discusses image loading http://stackoverflow.com/questions/33969872/webpack-sass-loader-cannot-find-images – Tudor Ilisoi Jan 21 '17 at 18:48
  • @Paulos3000 : As you are using Absolute path, your image need to be present in the Dist/Output folder [from where you are serving the index.html, reactbundle.js, css] in the respective structure '/img/spritesheet.png'. It would be better if you can share your git code snippet for clear understanding of Webpack config etc. – Ravi Roshan Jan 21 '17 at 19:49
  • @Ravi - I am serving the images from the dist folder (called `static` in my case). Please see update, I have provided a bit more detail on the file tree, and my `package.json` and `webpack.config.js`. – Paulos3000 Jan 21 '17 at 19:59
  • @Paulos3000 : As you are using absolute path, Webpack won't throw any error during compilation for the image. Still not able to figure out, Just check your browser network connection - verify where it is pointing to or are you getting any error on browser console. Also, just try playing around with your ' publicPath: "/js/", i.e. use ' publicPath: "/", and while importing the bundle.js in index.html, make the changes. I am assuming you are using Webpack-Dev-Server – Ravi Roshan Jan 21 '17 at 20:10

2 Answers2

2

I ran into the same problem. I found that you can include ?url=false in your css-loader to disable url handling. Then you can just place an image in your public folder for css to access. The image won't be run through webpack, but it will get you past webpack's compile errors and still allow images to be accessed.

So here is my new object in the module.loaders array:

{
    test: /\.s?css$/,
    use: ExtractTextPlugin.extract({
        fallback: 'style-loader',
        use: ['css-loader?url=false', 'sass-loader']
    })
}
strausd
  • 401
  • 3
  • 11
0

Ok, I found the answer on another stack overflow question: Webpack - background images not loading

It turns out it was a bug, caused by the sourceMap of css-loader.

I changed this...

{
   test: /\.scss$/,
   loaders: [ 'style', 'css?sourceMap', 'sass?sourceMap' ]
}

...to this:

{
   test: /\.scss$/,
   loaders: [ 'style', 'css', 'sass?sourceMap' ]
}

Hope that helps anyone else who faces this problem as it wasted a good few hours for me!

Community
  • 1
  • 1
Paulos3000
  • 3,355
  • 10
  • 35
  • 68