5

I'm creating a banner-like component with image set as a component's background but I can't get it to work. I tried different suggestions posted online to no luck and at the moment I'm not sure whether my mistake is within react code or it's the webpack that doesn't load the files correctly.

Here's my file structure:

AppFolder
 - client/
 -- components/
 -- data/
 -- images/
 ----- banners/
 ------- frontPageBanner2.png
    ------- 
 -- styles/
 -- myApp.js
 -- store.js
    ---------
 - index.html
 - package.json
 - webpack.config.dev.js

Here's my webpack configuration:

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

module.exports = {
  devtool: 'source-map',
  entry: [
    'webpack-hot-middleware/client',
    './client/myApp'
  ],
  output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/static/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ],
  module: {
    loaders: [
    // js
    {
      test: /\.js$/,
      exclude: /node_modules/,
      loaders: ['babel'],
      presets: ['es2015', 'react'],
      include: path.join(__dirname, 'client')
    },
    // CSS
    { 
      test: /\.scss$/,
      include: path.join(__dirname, 'client'),
      loader: 'style-loader!css-loader!sass-loader'
    },

    //    PNG
    {
      test: /\.(jpg|png)$/,
      loader: "url-loader?limit=25000",
      //loader: 'file?name=[path][name].[ext]',
      include: path.join(__dirname, 'client')
    },

    // FontAwesome
    { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" },
    { test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
      exclude: path.join(__dirname, 'client/images'),
      loader: "file-loader" },

    // other SVG
    { test: /\.svg$/,
      loader: 'url-loader',
      query: { mimetype: "image/svg+xml" },
      include: path.join(__dirname, 'client/images')
    },

   ]
  }
};

And here's how I'm using it in the app:

export class Banner extends React.Component {
    render() {
        console.log(this.props.banners);
        // = '../images/banners/frontPageBanner.png'
        const bannerImg = this.props.image.backgroundImage;

        var bannerStyle = {
            background: 'url(' + bannerImg + ')',
            backgroundSize: this.props.image.backgroundSize,
            backgroundPosition: this.props.image.backgroundPosition,
        }

        return (
            <section key={this.props.key} className="container hero" style={bannerStyle}>
                <div className="textbox">
                    <h2>{this.props.title}</h2>
                </div>
            </section>
        )
    }
}

Here's resulting html:

<section class="container hero" style="background: url('../images/banners/frontPageBanner2.png') 100% 100% / contain;">
    ...
</section>

but no image is displayed. Also opening the image src link shows just a blank screen. Why? And how can i fix it?

spik3s
  • 1,189
  • 2
  • 11
  • 27

1 Answers1

18

You should pass a var that is the result of requiring the image, when you require it using webpack, it'll generate a base64 inline image, not a relative path.

var DuckImage = require('./Duck.jpg');

var bannerStyle = {
    backgroundImage: 'url(' + DuckImage + ')',
    backgroundSize: this.props.image.backgroundSize,
    backgroundPosition: this.props.image.backgroundPosition,
}
Rafael Angeline
  • 337
  • 3
  • 7
  • I've tried that and yes if I manually insert a path into `require()` it works. However, the component should be dynamic and URL has to be read from the props. `require(this.props.image.backgroundImage)` won't work... – spik3s May 23 '16 at 09:28
  • 1
    You can always load the image and pass to a props, but if the URLs are really dynamic and shouldn't be bundled in your app, you definitely need to pass the absolute path - 'http://localhost/myapp/public/img/myimage.jpg' for example. Then you won't need to use the require and your app will be smaller. – Rafael Angeline May 23 '16 at 18:12
  • That's what I ended up doing, I serve photos from the same server as JSON data with URLs, using absolute paths. Thanks for helping out! – spik3s May 24 '16 at 14:13