React import images from public folder

12,102

Solution 1

You are using file-loader as webpack plugin, which does not work in the way of "just mirroring the directory structure of public to dist". You can find the documentation for that plugin here: https://webpack.js.org/loaders/file-loader/

Basically, what the plugin does is, if you import an image file (actually programatically importing it, not just using a string reference to its path), the file is copied to your dist directory, potentially renamed and than in your compiled source code the proper file name is inserted.

So in your case, if you want to solve your problem using file-loader, you would reference the image file like

// Relative path to image file from js file
import imageFile from './assets/image.png';

// ...
const component = props => <img src={imageFile}></img>;

If you want to use the approach of actually just mirroring a public-directory to the dist directory, you need to use an additional webpack-plugin for that (e.g. https://stackoverflow.com/a/33374807/2692307)

By the way, I assume it works in dev-mode because you are setting '/' as public path, so the development server just serves everything in the root directory as well. That is something different than copying the files to dist however as you are trying to achieve.

Solution 2

I assume you want to display such image more than once. In that case, is annoying to keep writing something like '%PUBLIC_URL%/img/static/images/image.png' or {process.env.PUBLIC_URL + '/img/static/images/image.png'} two, three or more times within your jsx code. Basically, without a plugin is imposible to import images from the public folder if your app is rooted in the src folder. However I did find a solution for me and was quite simple in fact. It was something like this:

import React from 'react'

var path = process.env.PUBLIC_URL;
var image = "/img/static/images/image.png";

and then, within jsx code:

<img src={path + image}/>

it worked for me, hope this is helpful for anyone! :D

Share:
12,102
7xRobin
Author by

7xRobin

Updated on June 07, 2022

Comments

  • 7xRobin
    7xRobin almost 2 years

    I'm trying to get static images fro my public directory but is not being found. I'm not using CRA, so maybe is some configuration with Webpack that I'm missing. Using file-loader module and importing the image works on Dev Mode, but doesn't work in for my production server specification

    My Project structure:

    \public
       \static
          \images
             image.png
    \src
       \component
          component.js
    ...
    package.json
    webpack.common.js
    webpack.dev.js
    webpack.prod.js
    

    On component.js, I want to get image.jpg on static/images folder like this:

      <img src='/static/images/image.png'></img>
    

    But I'm getting a 404 not found.

    My webpack.commom.js:

    const CleanWebPackPlugin = require('clean-webpack-plugin')
    const HtmlWebPackPlugin = require('html-webpack-plugin')
    const path = require('path')
    
    module.exports = {
        entry: {
            main: './src/index.js'
        },
        output: {
            filename: '[name].[hash].js',
            path: path.resolve('./dist'),
            publicPath: "/"
        },
        module:{
            rules:[
                {
                    test: /\.js$/,
                    exclude: ['/node_modules'],
                    use: [{ loader: 'babel-loader'}],
                },
                {
                    test: /\.s?(a|c)ss$/,
                    use: [{
                        loader: 'style-loader'
                    }, {
                        loader: 'css-loader'
                    },{
                        loader: 'sass-loader'
                    }]
                },
                {
                    test: /\.(png|jpe?g|gif)$/,
                    use: [
                      {
                        loader: 'file-loader',
                        options: {},
                      },
                    ],
                  },
    
            ]
        },
        plugins: [
            new HtmlWebPackPlugin({
                template: 'index.html'
            }),
            new CleanWebPackPlugin(),
        ],
    }
    

    And the Dev version:

    module.exports = merge(common, {
        mode: 'development',
        devServer: {
            host: 'localhost',
            port: 3000,
            open: true,
            historyApiFallback: true,
            publicPath: "/",
        }
    })
    

    Thank you in advance.

    • callmeroot
      callmeroot over 4 years
      A couple things: You are setting 'src' as '/static/image.png' but according to your project structure it should be '/static/images/image.png'. Was that a typo? What does your 'dist/' folder look like after running a production build? Does it include that image file?
    • 7xRobin
      7xRobin over 4 years
      It was a typo error, indeed. In the production dist/ fold appears the image just if I import by the loader webpack plugin, which is not a good option for me.
  • 7xRobin
    7xRobin over 4 years
    The import using file-loader works, but I need to access the source directly from the public path like <img src='/static/images/image.png'></img>. But the dev server doesn't find the sources. This is the big problem. The copy-webpack-plugin solved my problem, but not sure why. Thank you, anyway.