Cómo cargar archivos de imagen con el cargador de archivos webpack

141

Estoy usando webpack para gestionar un proyecto reactjs . Quiero cargar imágenes en javascript por webpack file-loader. A continuación se muestra el webpack.config.js :

const webpack = require('webpack');
const path = require('path');
const NpmInstallPlugin = require('npm-install-webpack-plugin');

const PATHS = {
    react: path.join(__dirname, 'node_modules/react/dist/react.min.js'),
    app: path.join(__dirname, 'src'),
    build: path.join(__dirname, './dist')
};

module.exports = {
    entry: {
        jsx: './app/index.jsx',
    },
    output: {
        path: PATHS.build,
        filename: 'app.bundle.js',
    },
    watch: true,
    devtool: 'eval-source-map',
    relativeUrls: true,
    resolve: {
        extensions: ['', '.js', '.jsx', '.css', '.less'],
        modulesDirectories: ['node_modules'],
        alias: {
            normalize_css: __dirname + '/node_modules/normalize.css/normalize.css',
        }
    },
    module: {
        preLoaders: [

            {
                test: /\.js$/,
                loader: "source-map-loader"
            },
        ],
        loaders: [

            {
                test: /\.html$/,
                loader: 'file?name=[name].[ext]',
            },
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                loader: 'babel-loader?presets=es2015',
            },
            {test: /\.css$/, loader: 'style-loader!css-loader'},
            {test: /\.(jpe?g|png|gif|svg)$/i, loader: "file-loader?name=/public/icons/[name].[ext]"},
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loaders: ['babel-loader?presets=es2015']
            }
        ]
    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false,
            },
            output: {
                comments: false,
            },
        }),
        new NpmInstallPlugin({
            save: true // --save
        }),
        new webpack.DefinePlugin({
            "process.env": {
                NODE_ENV: JSON.stringify("production")
            }
        }),
    ],
    devServer: {
        colors: true,
        contentBase: __dirname,
        historyApiFallback: true,
        hot: true,
        inline: true,
        port: 9091,
        progress: true,
        stats: {
            cached: false
        }
    }
}

Usé esta línea para cargar archivos de imagen y copiarlos en el directorio dist / public / icons y mantener el mismo nombre de archivo.

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

Pero tengo dos problemas cuando lo uso. Cuando ejecuto el webpackcomando, el archivo de imagen se copió al directorio dist / public / icons / como se esperaba. Sin embargo, también se copió al directorio dist con este nombre de archivo "df55075baa16f3827a57549950901e90.png".

A continuación se muestra la estructura de mi proyecto: ingrese la descripción de la imagen aquí

Otro problema es que utilicé el siguiente código para importar este archivo de imagen, pero no se muestra en el navegador. Si estoy usando la url 'public / icons / imageview_item_normal.png' en la etiqueta img, funciona bien. ¿Cómo usar el objeto importado del archivo de imagen?

import React, {Component} from 'react';
import {render} from 'react-dom';
import img from 'file!../../public/icons/imageview_item_normal.png'

export default class MainComponent extends Component {

  render() {
    return (
      <div style={styles.container}>
        download
        <img src={img}/>
      </div>
    )
  }

}

const styles = {
  container: {
    width: '100%',
    height: '100%',
  }
}
Joey Yi Zhao
fuente
1
¿Has intentado eliminar el cargador de URL?
Jaime
Eliminé el cargador de url del archivo de configuración de webpack y eliminé el directorio dist y volví a ejecutar el comando webpack, el problema sigue ahí. El archivo fue generado.
Joey Yi Zhao

Respuestas:

196

Sobre el problema # 1

Una vez que haya configurado el cargador de archivos en webpack.config, cada vez que use import / require, probará la ruta contra todos los cargadores, y en caso de que haya una coincidencia, pasará el contenido a través de ese cargador. En tu caso, coincidía

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

y por lo tanto ves la imagen emitida a

dist/public/icons/imageview_item_normal.png

cual es el comportamiento deseado.

La razón por la que también obtiene el nombre del archivo hash es porque está agregando un cargador de archivos en línea adicional. Estás importando la imagen como:

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

Prefijar con file!, pasa el archivo al cargador de archivos nuevamente, y esta vez no tiene la configuración de nombre.

Entonces su importación realmente debería ser:

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

Actualizar

Como señaló @cgatian, si realmente desea utilizar un cargador de archivos en línea, ignorando la configuración global del paquete web, puede prefijar la importación con dos signos de exclamación (!!):

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

Sobre el problema # 2

Después de importar png, la imgvariable solo contiene la ruta que el cargador de archivos "conoce", que es public/icons/[name].[ext](alias "file-loader? name=/public/icons/[name].[ext]"). Su directorio de salida "dist" es desconocido. Podrías resolver esto de dos maneras:

  1. Ejecute todo su código en la carpeta "dist"
  2. Agregue publicPathpropiedad a su configuración de salida, que apunta a su directorio de salida (en su caso ./dist).

Ejemplo:

output: {
  path: PATHS.build,
  filename: 'app.bundle.js',
  publicPath: PATHS.build
},
omerts
fuente
153
ESTE ES EL ÚNICO DOCUMENTO EN TODA LA INTERNET que dice "publicPath" cambiará la URL utilizada por el cargador de archivos.
Tyler Jones
@TylerJones, ¿qué quieres decir?
Sagiv bg
1
@ Sag1v, creo que es mejor que publique una nueva pregunta, con más información, incluida la configuración de su paquete web
omerts
1
Solo para agregar a la respuesta. (edite, ya que creo que esto es útil) Si se encuentra en una situación en la que desea omitir la configuración del paquete web en una declaración obligatoria, puede agregar dos explosiones adicionales antes de la importaciónrequire('!!file-loader!wenis.png');
cgatian
2
La documentación ha mejorado mucho desde las afirmaciones anteriores :) - Consulte: github.com/webpack-contrib/file-loader#options y más información sobre publicPath: github.com/webpack-contrib/file-loader#publicpath
Pavelloz
15

Tuve un problema al cargar imágenes en mi proyecto React JS. Estaba tratando de usar el cargador de archivos para cargar las imágenes; También estaba usando Babel-loader en mi reacción.

Usé la siguiente configuración en el paquete web:

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

Esto ayudó a cargar mis imágenes, pero las imágenes cargadas estaban algo corruptas. Luego, después de algunas investigaciones, llegué a saber que el cargador de archivos tiene el error de corromper las imágenes cuando se instala el cargador de babel.

Por lo tanto, para solucionar el problema, intenté usar el cargador de URL que funcionó perfectamente para mí.

Actualicé mi paquete web con la siguiente configuración

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

Luego usé el siguiente comando para importar las imágenes

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

      <img  style={{ width: 300, height: 150 }} src={img} />
</div>
usuario3717160
fuente
6

Instale el cargador de archivos primero:

$ npm install file-loader --save-dev

Y agregue esta regla en webpack.config.js

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

Alternativamente, puedes escribir lo mismo que

{
    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'
        }
    }
}

y luego usar importación simple

import varName from 'relative path';

y en jsx escribe como <img src={varName} ..../>

.... son para otros atributos de imagen

Gaurav Paliwal
fuente
1
Esta parte final es muy importante para las imágenes insertadas por jsx gracias @ gaurav-paliwal. el uso de import imgPath me ayudó a resolverlo y las imágenes se copiaron en la carpeta dist / build
Ebrahim
1
Esa outputPathclave me ayudó a descubrir dónde colocar archivos con subcarpetas y todo eso. Las otras respuestas aquí no funcionaron. Muchas gracias.
Thielicious
0

webpack.config.js

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

anyfile.html

<img src={image_name.jpg} />
Анов Алексей
fuente
0

Este es mi ejemplo de trabajo de nuestro componente Vue simple.

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