4

I am building a ReactJS App using webpack.

This simple example should render an <img> with a given url as src-attribute.

How can I bundle the image resource with webpack and process it via an appropriate loader? I can't figure out, why the image resource does not get bundled.

I don't include the generated admin.bundle.js like this <script src="/admin/dist/admin.bundle.js"></script>, because I am not talking about the prod Environment. I am just using webpack-dev-server --inline --hot, so I am including the admin.bundle.js like this: <script src="http://localhost:8080/admin/dist/admin.bundle.js"></script> which totally works.

import React from 'react';
import { Container, Image } from 'semantic-ui-react';
import MainMenu from './menu/components/MainMenu';

const App = () => (
  <Container>
    <Image src="/res/img/image.png" />
    <MainMenu />
  </Container>
);

export default App;

The directory structure of my (Symfony and ReactJS) project is as follows (I ommited irrelevant directories/files to clarify):

.
├── README.md
├── app
│   ├── AppCache.php
│   ├── AppKernel.php
│   ├── Resources
│   │   ├── client
│   │   │   └── admin
│   │   │       ├── node_modules
│   │   │       ├── package.json
│   │   │       ├── src
│   │   │       │   ├── App.jsx
│   │   │       │   ├── index.jsx
│   │   │       │   ├── menu
│   │   │       │   └── res
│   │   │       ├── webpack.config.js
│   │   └── views
│   └── config
└── web
    ├── admin
    │   ├── dist
    ├── app.php
    └── app_dev.php

My webpack.config.js goes like:

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

const basePath = path.normalize(__dirname + '/../../../../');

module.exports = {
  entry: [
    './src/index.jsx'
  ],
  output: {
    filename: 'admin.bundle.js',
    publicPath: '/admin/dist/',
    path: path.resolve(basePath, 'web', 'admin', 'dist')
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
  ],
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: [ 'react-hot-loader', 'babel-loader', 'eslint-loader' ]
      },
      {
        test: /\.css$/,
        use: [ 'style-loader', 'css-loader' ]
      },
      {
        test: /\.(png|jpg)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 40000 // 40 kB
            }
          }
        ]
      },
      {
        test: /\.(eot|woff|woff2|svg|ttf)([\?]?.*)$/,
        loader: "file-loader"
      }
    ]
  },

  resolve: {
    modules: [
      path.resolve(__dirname, 'src'),
      'node_modules'
    ],
    extensions: [ '.js', '.jsx' ]
  },

  devServer: {
    hot: true,
    inline: true
  }
};
ILCAI
  • 1,164
  • 2
  • 15
  • 35

1 Answers1

7

In order for webpack to bundle your image you need to import it like you would any other resource. Not sure if the paths are correct, as I don't know where your image is located, but this is the general idea.

import React from 'react';
import { Container, Image } from 'semantic-ui-react';
import MainMenu from './menu/components/MainMenu';

import myImage from '/res/img/image.png';

const App = () => (
  <Container>
    <Image src={ myImage } />
    <MainMenu />
  </Container>
);

export default App;
ryandrewjohnson
  • 555
  • 3
  • 7
  • Thank you. That does the trick. I was just convinced of the fact, that a loader would also scan referenced resources via components' props ... – ILCAI Aug 08 '17 at 08:05
  • It is a bit confusing as it will automagically pick up the URL when used in CSS e.g. background-image: url(/res/img/image.png) – ryandrewjohnson Aug 08 '17 at 11:49