Accepted answer

Regarding problem #1

Once you have the file-loader configured in the webpack.config, whenever you use import/require it tests the path against all loaders, and in case there is a match it passes the contents through that loader. In your case, it matched

    test: /\.(jpe?g|png|gif|svg)$/i, 
    loader: "file-loader?name=/public/icons/[name].[ext]"

// For newer versions of Webpack it should be
    test: /\.(jpe?g|png|gif|svg)$/i, 
    loader: 'file-loader',
    options: {
      name: '/public/icons/[name].[ext]'

and therefore you see the image emitted to


which is the wanted behavior.

The reason you are also getting the hash file name, is because you are adding an additional inline file-loader. You are importing the image as:


Prefixing with file!, passes the file into the file-loader again, and this time it doesn't have the name configuration.

So your import should really just be:

import img from '../../public/icons/imageview_item_normal.png'


As noted by @cgatian, if you actually want to use an inline file-loader, ignoring the webpack global configuration, you can prefix the import with two exclamation marks (!!):

import '!!file!../../public/icons/imageview_item_normal.png'.

Regarding problem #2

After importing the png, the img variable only holds the path the file-loader "knows about", which is public/icons/[name].[ext] (aka "file-loader? name=/public/icons/[name].[ext]"). Your output dir "dist" is unknown. You could solve this in two ways:

  1. Run all your code under the "dist" folder
  2. Add publicPath property to your output config, that points to your output directory (in your case ./dist).


output: {
  filename: 'app.bundle.js',



    test: /\.(png|jpe?g|gif)$/i,
    loader: 'file-loader',
    options: {
        name: '[name].[ext]',


<img src={image_name.jpg} />


This is my working example of our simple Vue component.

<template functional>
    <div v-html="require('!!html-loader!./../svg/logo.svg')"></div>


Alternatively you can write the same like

    test: /\.(svg|png|jpg|jpeg|gif)$/,
    include: 'path of input image directory',
    use: {
        loader: 'file-loader',
        options: {
            name: '[path][name].[ext]',
            outputPath: 'path of output image directory'

and then use simple import

import varName from 'relative path';

and in jsx write like <img src={varName} ..../>

.... are for other image attributes


Install file loader first:

$ npm install file-loader --save-dev

And add this rule in webpack.config.js

                test: /\.(png|jpg|gif)$/,
                use: [{
                    loader: 'file-loader',
                    options: {}


I had an issue uploading images to my React JS project. I was trying to use the file-loader to load the images; I was also using Babel-loader in my react.

I used the following settings in the webpack:

{test: /\.(jpe?g|png|gif|svg)$/i, loader: "file-loader?name=app/images/[name].[ext]"},

This helped load my images, but the images loaded were kind of corrupted. Then after some research I came to know that file-loader has a bug of corrupting the images when babel-loader is installed.

Hence, to work around the issue I tried to use URL-loader which worked perfectly for me.

I updated my webpack with the following settings

{test: /\.(jpe?g|png|gif|svg)$/i, loader: "url-loader?name=app/images/[name].[ext]"},

I then used the following command to import the images

import img from 'app/images/GM_logo_2.jpg'
<div className="large-8 columns">

      <img  style={{ width: 300, height: 150 }} src={img} />

Related Query

More Query from same tag