Comment charger des fichiers image avec le chargeur de fichiers Webpack

141

J'utilise webpack pour gérer un projet reactjs . Je souhaite charger des images en javascript par webpack file-loader. Voici le 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
        }
    }
}

J'ai utilisé cette ligne pour charger les fichiers image et les copier dans le répertoire dist / public / icons et conserver le même nom de fichier.

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

Mais j'ai deux problèmes lors de son utilisation. Lorsque j'exécute la webpackcommande, le fichier image a été copié dans le répertoire dist / public / icons / comme prévu. Cependant, il a également été copié dans le répertoire dist avec ce nom de fichier "df55075baa16f3827a57549950901e90.png".

Voici la structure de mon projet: entrez la description de l'image ici

Un autre problème est que j'ai utilisé le code ci-dessous pour importer ce fichier image mais il ne s'affiche pas sur le navigateur. Si j'utilise l'url 'public / icons / imageview_item_normal.png' sur la balise img, cela fonctionne bien. Comment utiliser l'objet importé du fichier image?

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
la source
1
Avez-vous essayé de supprimer le chargeur d'url?
Jaime
J'ai supprimé le chargeur d'url du fichier de configuration webpack et supprimé le répertoire dist et réexécuté la commande webpack, le problème est toujours là. Le fichier a été généré.
Joey Yi Zhao

Réponses:

197

Concernant le problème n ° 1

Une fois que vous avez configuré le chargeur de fichiers dans le webpack.config, chaque fois que vous utilisez import / require, il teste le chemin par rapport à tous les chargeurs, et en cas de correspondance, il transmet le contenu à ce chargeur. Dans votre cas, cela correspondait

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

et donc vous voyez l'image émise vers

dist/public/icons/imageview_item_normal.png

qui est le comportement recherché.

La raison pour laquelle vous obtenez également le nom du fichier de hachage est que vous ajoutez un chargeur de fichiers en ligne supplémentaire. Vous importez l'image en tant que:

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

En préfixant avec file!, passe à nouveau le fichier dans le chargeur de fichiers, et cette fois il n'a pas la configuration de nom.

Votre importation devrait donc être:

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

Mettre à jour

Comme indiqué par @cgatian, si vous souhaitez réellement utiliser un chargeur de fichiers en ligne, en ignorant la configuration globale du webpack, vous pouvez préfixer l'importation avec deux points d'exclamation (!!):

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

Concernant le problème n ° 2

Après avoir importé le png, la imgvariable ne contient que le chemin que le chargeur de fichiers "connaît", qui est public/icons/[name].[ext](aka "file-loader? name=/public/icons/[name].[ext]"). Votre répertoire de sortie "dist" est inconnu. Vous pouvez résoudre ce problème de deux manières:

  1. Exécutez tout votre code dans le dossier "dist"
  2. Ajoutez une publicPathpropriété à votre configuration de sortie, qui pointe vers votre répertoire de sortie (dans votre cas ./dist).

Exemple:

output: {
  path: PATHS.build,
  filename: 'app.bundle.js',
  publicPath: PATHS.build
},
omerts
la source
153
CECI EST LE SEUL DOCUMENT SUR TOUT INTERNET indiquant que "publicPath" changera l'url utilisée par le chargeur de fichiers.
Tyler Jones
@TylerJones que voulez-vous dire?
Sagiv bg
1
@ Sag1v, je pense qu'il vaut mieux que vous postez une nouvelle question, avec plus d'informations, y compris votre configuration
webpack
1
Juste pour ajouter à la réponse. (veuillez modifier car je pense que cela est utile) Vous si vous vous trouvez dans une situation où vous souhaitez contourner la configuration du webpack sur une instruction require, vous pouvez ajouter deux franges supplémentaires avant l'importationrequire('!!file-loader!wenis.png');
cgatian
2
La documentation a été grandement améliorée depuis les revendications ci-dessus :) - Voir: github.com/webpack-contrib/file-loader#options et plus d'informations sur publicPath: github.com/webpack-contrib/file-loader#publicpath
Pavelloz
15

J'ai rencontré un problème lors du téléchargement d'images dans mon projet React JS. J'essayais d'utiliser le chargeur de fichiers pour charger les images; J'utilisais aussi Babel-loader dans ma réaction.

J'ai utilisé les paramètres suivants dans le pack Web:

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

Cela a aidé à charger mes images, mais les images chargées étaient en quelque sorte corrompues. Ensuite, après quelques recherches, j'ai appris que le chargeur de fichiers avait un bogue de corruption des images lorsque babel-loader était installé.

Par conséquent, pour contourner le problème, j'ai essayé d'utiliser le chargeur d'URL qui fonctionnait parfaitement pour moi.

J'ai mis à jour mon pack Web avec les paramètres suivants

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

J'ai ensuite utilisé la commande suivante pour importer les images

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

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

Installez d'abord le chargeur de fichiers:

$ npm install file-loader --save-dev

Et ajoutez cette règle dans webpack.config.js

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

Sinon, vous pouvez écrire la même chose comme

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

puis utilisez l'importation simple

import varName from 'relative path';

et en jsx écrivez comme <img src={varName} ..../>

.... sont pour d'autres attributs d'image

Gaurav Paliwal
la source
1
Cette partie finale est très importante pour les images insérées par jsx merci @ gaurav-paliwal. l'utilisation d'import imgPath m'a aidé à le résoudre et les images ont été copiées dans le dossier dist / build
Ebrahim
1
Cette outputPathclé m'a aidé à déterminer où placer les fichiers avec des sous-dossiers et tout ça. Les autres réponses ici n'ont pas fonctionné. Merci beaucoup.
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} />
Янов Алексей
la source
0

Ceci est mon exemple de travail de notre composant Vue simple.

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