Come caricare file di immagini con il caricatore di file webpack


141

Sto usando il webpack per gestire un progetto reazioni . Voglio caricare immagini in javascript tramite webpack file-loader. Di seguito è il 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
        }
    }
}

Ho usato questa linea per caricare i file di immagine e copiarli nella directory dist / public / icons e mantenere lo stesso nome di file.

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

Ma ho due problemi durante l'utilizzo. Quando eseguo il webpackcomando, il file di immagine viene copiato nella directory dist / public / icons / come previsto. Tuttavia, è stato anche copiato nella directory dist con questo nome file "df55075baa16f3827a57549950901e90.png".

Di seguito è riportata la struttura del mio progetto: inserisci qui la descrizione dell'immagine

Un altro problema è che ho usato il codice seguente per importare questo file immagine ma non viene visualizzato sul browser. Se sto usando l'URL 'public / icons / imageview_item_normal.png' sul tag img, funziona benissimo. Come usare l'oggetto importato dal file immagine?

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%',
  }
}

1
Hai provato a rimuovere url-loader?
Jaime,

Ho rimosso url-loader dal file di configurazione webpack e rimosso la directory dist ed eseguito nuovamente il comando webpack, il problema è ancora lì. Il file è stato generato.
Joey Yi Zhao,

Risposte:


197

Per quanto riguarda il problema n. 1

Una volta configurato il caricatore di file in webpack.config, ogni volta che si utilizza import / richiedi verifica il percorso su tutti i caricatori e, in caso di corrispondenza, passa il contenuto attraverso quel caricatore. Nel tuo caso, ha abbinato

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

e quindi vedi l'immagine emessa

dist/public/icons/imageview_item_normal.png

quale è il comportamento desiderato.

Il motivo per cui stai anche ottenendo il nome del file hash è perché stai aggiungendo un caricatore di file inline aggiuntivo. Stai importando l'immagine come:

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

Il prefisso con file!, passa nuovamente il file nel caricatore di file e questa volta non ha la configurazione del nome.

Quindi la tua importazione dovrebbe essere davvero:

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

Aggiornare

Come notato da @cgatian, se si desidera effettivamente utilizzare un caricatore di file in linea, ignorando la configurazione globale del webpack, è possibile aggiungere un prefisso all'importazione con due punti esclamativi (!!):

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

Per quanto riguarda il problema n. 2

Dopo aver importato il png, la imgvariabile mantiene solo il percorso che il caricatore di file "conosce", che è public/icons/[name].[ext](aka "file-loader? name=/public/icons/[name].[ext]"). La tua directory di output "dist" non è nota. Puoi risolverlo in due modi:

  1. Esegui tutto il codice nella cartella "dist"
  2. Aggiungi publicPathproprietà alla tua configurazione di output, che punta alla tua directory di output (nel tuo caso ./dist).

Esempio:

output: {
  path: PATHS.build,
  filename: 'app.bundle.js',
  publicPath: PATHS.build
},

153
QUESTO È L'UNICO DOCUMENTO SULL'INTERA INTERNET che dice "publicPath" cambierà l'URL utilizzato dal caricatore di file.
Tyler Jones,

@TylerJones che vuoi dire?
Sagiv,

1
@ Sag1v, penso che sia meglio per te pubblicare una nuova domanda, con ulteriori informazioni tra cui la configurazione del tuo webpack
omissioni

1
Solo per aggiungere alla risposta. (per favore modifica come penso che sia utile) Se ti trovi in ​​una situazione in cui vuoi bypassare la configurazione del webpack su una dichiarazione obbligatoria puoi aggiungere due ulteriori colpi prima dell'importazionerequire('!!file-loader!wenis.png');
cgatian

2
La documentazione è stata notevolmente migliorata da quanto sopra rivendicato :) - Vedi: github.com/webpack-contrib/file-loader#options e maggiori informazioni su publicPath: github.com/webpack-contrib/file-loader#publicpath
Pavelloz

15

Ho riscontrato un problema durante il caricamento delle immagini nel mio progetto React JS. Stavo cercando di utilizzare il caricatore di file per caricare le immagini; Stavo anche usando Babel-loader nella mia reazione.

Ho usato le seguenti impostazioni nel webpack:

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

Questo mi ha aiutato a caricare le mie immagini, ma le immagini caricate sono state corrotte. Poi, dopo alcune ricerche, ho scoperto che il caricatore di file ha un bug nel corrompere le immagini quando è installato il caricatore di babele.

Quindi, per aggirare il problema, ho provato a utilizzare il caricatore di URL che ha funzionato perfettamente per me.

Ho aggiornato il mio webpack con le seguenti impostazioni

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

Ho quindi usato il seguente comando per importare le immagini

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

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

6

Installa prima il caricatore di file:

$ npm install file-loader --save-dev

E aggiungi questa regola in webpack.config.js

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

5

In alternativa puoi scrivere lo stesso come

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

e quindi utilizzare l'importazione semplice

import varName from 'relative path';

e in jsx scrivi come <img src={varName} ..../>

.... sono per altri attributi di immagine


1
Questa parte finale è molto importante per le immagini inserite da jsx grazie a @ gaurav-paliwal. usando import imgPath mi ha aiutato a risolverlo e le immagini sono state copiate nella cartella dist / build
Ebrahim,

1
Quella outputPathchiave mi ha aiutato a capire dove posizionare i file con le sottocartelle e tutto il resto. Le altre risposte qui non hanno funzionato. Molte grazie.
Thielicious il

0

webpack.config.js

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

anyfile.html

<img src={image_name.jpg} />

0

Questo è il mio esempio di lavoro del nostro semplice componente Vue.

<template functional>
    <div v-html="require('!!html-loader!./../svg/logo.svg')"></div>
</template>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.