1

I'm currently working on a project using React and webpack, but I'm new to both. I need to display an image from the server's filesystem. I'm attempting to use webpack's file-loader to display the image, but I'm having trouble getting it to work.

Edit: I've made a couple changes due to some suggestions and I'm having a slightly different problem than my original problem. After switching from requiring the image to importing the image, I now get a correct file path, "images/7047aa4de98575625fc771ca68618c28.png". I now have my webpack file-loader outputing to that directory, and I do have an image called images/7047aa4de98575625fc771ca68618c28.png on my filesystem, but I get a 404 NOT FOUND response when I attempt to display the image.

My webpack config is here:

var path = require('path');

module.exports = {
    entry: './src/main/js/app.js',
    devtool: 'sourcemaps',
    cache: true,
    mode: 'development',
    output: {
        path: __dirname,
        filename: './src/main/resources/static/built/bundle.js'
    },
    module: {
        rules: [
            {
              test: /\.(jpg|png|svg)$/i,
              loader: 'file-loader',
              options: {
                outputPath: 'images',
              }
            },
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: [{
                    loader: 'babel-loader',
                    options: {
                        presets: ["@babel/preset-env", "@babel/preset-react"]
                    }
                }]
            }
        ]
    }
};

And the relevant part of my code attempting to get the image is here:

// const catImage = require('./data/images/cat.png');
import catImage from './data/images/cat.png';

const root = '/api';

class App extends React.Component {
  render() {
    return (
      <BrowserRouter>
        <div>
          <Switch>
            <Route path="/" component={Upload} exact />
            <Route path="/share/:key" component={Share} />
            <Route path="/test" component={Test} />
            <Route component={Error}/>
          </Switch>
        </div>
      </BrowserRouter>
    )
  }
}

class Test extends React.Component {
  render() {
    const gat = catImage;

    return (
      <div>
        <img src={gat} />
      </div>
    )
  }
}
Jake
  • 11
  • 3
  • What do you get by logging `catImage`? – Camilo Oct 30 '20 at 03:15
  • Skip using require and directly use the URL in the image source like – Sivakumar Oct 30 '20 at 03:17
  • Good question! I get this: __esModule: true ​ default: "7047aa4de98575625fc771ca68618c28.png" ​ Symbol(Symbol.toStringTag): "Module" – Jake Oct 30 '20 at 03:19
  • I suggest using `import` instead of `require`. Like in the examples https://webpack.js.org/loaders/file-loader/#examples – Camilo Oct 30 '20 at 03:20
  • Actually, your suggestion helped me realize that my webpack appears to be dumping the image in my top level source directory, as I have 7047aa4de98575625fc771ca68618c28.png there. Do you know how I can control where this image actually gets dumped? – Jake Oct 30 '20 at 03:21
  • Yes, see https://webpack.js.org/loaders/file-loader/#outputpath – Camilo Oct 30 '20 at 03:22
  • 1
    I tried using import instead of require and it seems to be working better, although I'm getting a 404. I think I just have to make sure my source code is actually looking in the right spot. The request is now GET localhost:8080/7047aa4de98575625fc771ca68618c28.png, which seems promising – Jake Oct 30 '20 at 03:24
  • thank you! I will definitely be trying that out – Jake Oct 30 '20 at 03:25
  • Does this answer your question? [Webpack file-loader outputs \[object Module\]](https://stackoverflow.com/questions/59070216/webpack-file-loader-outputs-object-module) – Camilo Oct 30 '20 at 03:27
  • I added outputpath to my webpack config and I feel as though I am very close to getting it. Now my images are being put into /images and the get request is resolving to GET localhost:8080/images/7047aa4de98575625fc771ca68618c28.png The image IS in that directory with that name, but I'm getting 404 NOT FOUND. Do you perhaps know why this is? – Jake Oct 30 '20 at 03:31
  • The [object Module] changed to an actual file name when I switched from require to import. – Jake Oct 30 '20 at 03:33

1 Answers1

0

Switching to url-loader instead of file-loader made it work. I do not know why file-loader did not work. Oh well.

var path = require('path');

module.exports = {
    entry: './src/main/js/app.js',
    devtool: 'sourcemaps',
    cache: true,
    mode: 'development',
    output: {
        path: __dirname,
        filename: './src/main/resources/static/built/bundle.js'
    },
    module: {
        rules: [
            {
              test: /\.(jpg|png|svg)$/i,
              loader: 'url-loader',
              options: {
                outputPath: 'images',
              }
            },
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: [{
                    loader: 'babel-loader',
                    options: {
                        presets: ["@babel/preset-env", "@babel/preset-react"]
                    }
                }]
            }
        ]
    }
};

Make sure you use either

import image from './path/to/image.png';

OR

const image = require('./path/to/image.png');
const imageSrc = image.default;

You can also do:

const imagePath = require.context('./path/to/imageDirectory', true);
const imageSrc = imagePath('./image.png', true);
Jake
  • 11
  • 3