1

I'm using rails + webpack to compile a bundle.js file into the rails asset pipeline. I placed an image inside /app/assets/images called "main.png". How can I access this image inside a React component that's being bundled?

I'm using shakacode's react on rails gem. https://github.com/shakacode/react_on_rails

I then tried using webpack to process the image which it did successfully and placed the image next to the bundle.js file. I still get a 404 on the image.

I know I'm close, just have the publicPath wrong for the rails asset. This current setup gives a localhost:3000/webpack/main.png which isn't working with rails.

This is my webpack file:

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

const devBuild = process.env.NODE_ENV !== 'production';
const nodeEnv = devBuild ? 'development' : 'production';

config = {
  entry: [
    'es5-shim/es5-shim',
    'es5-shim/es5-sham',
    'babel-polyfill',
    './app/Register.js',
  ],

  output: {
    filename: 'webpack-bundle.js',
    path: '../app/assets/webpack',
    publicPath: '/webpack/'
  },

  resolve: {
    extensions: ['', '.js', '.jsx'],
    alias: {
      react: path.resolve('./node_modules/react'),
      'react-dom': path.resolve('./node_modules/react-dom'),
    },
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify(nodeEnv),
      },
    }),
  ],
  module: {
    loaders: [
      {
        test: require.resolve('react'),
        loader: 'imports?shim=es5-shim/es5-shim&sham=es5-shim/es5-sham',
      },
      {
        test: /\.jsx?$/, loader: 'babel-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.(png|svg)$/i,
        loaders: [
        'file?hash=sha512&digest=hex&name=[hash].[ext]',
        'image-webpack?bypassOnDebug&interlaced=false'
        ]
      }
    ],
  },
};

module.exports = config;

if (devBuild) {
  console.log('Webpack dev build for Rails'); // eslint-disable-line no-console
  module.exports.devtool = 'eval-source-map';
} else {
  config.plugins.push(
    new webpack.optimize.DedupePlugin()
  );
  console.log('Webpack production build for Rails'); // eslint-disable-line no-console
}
Dileet
  • 2,034
  • 3
  • 33
  • 53

1 Answers1

1

After defining a loader properly, you can load your image with a require function, for example! For example, add near your imports:

const myImg = require('./assets/methods.png');

Then, in your component's render method:

<img src={myImg} />

That should work...

Rafael Angeline
  • 337
  • 3
  • 7
  • But when webpack processes the image it gets renamed and place into the /webpack/ folder – Dileet Sep 10 '16 at 14:26
  • It's part of the bundle process made by Webpack. Most apps end up uploading the images to CDN providers, for example and using absolute URLs. `` – Rafael Angeline Sep 10 '16 at 20:27
  • 1
    Can you explain what you mean by defining a loader properly? I tried your suggestion but I get: "Cannot find module "./images/image001.svg" when I try to require the asset. – Riina Dec 03 '16 at 19:23
  • @Riina basically, you should declare a new loader at loaders object and ensure you installed it successfully. After that, you test for the file extension and link that to the loader(s) you want following the order you want. Like in the code above: ```{ test: /\.(png|svg)$/i, loaders: [ 'file?hash=sha512&digest=hex&name=[hash].[ext]', 'image-webpack?bypassOnDebug&interlaced=false' ] } ``` – Rafael Angeline Dec 04 '16 at 15:28