So laden Sie Bilddateien mit dem Webpack File-Loader

140

Ich verwende Webpack , um ein Reactjs- Projekt zu verwalten . Ich möchte Bilder in Javascript per Webpack laden file-loader. Unten ist die 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
        }
    }
}

Ich habe diese Zeile verwendet, um Bilddateien zu laden und sie in das Verzeichnis dist / public / icons zu kopieren und den gleichen Dateinamen beizubehalten.

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

Aber ich habe zwei Probleme bei der Verwendung. Wenn ich den webpackBefehl ausführe , wurde die Bilddatei wie erwartet in das Verzeichnis dist / public / icons / kopiert . Es wurde jedoch auch in das dist-Verzeichnis mit dem Dateinamen "df55075baa16f3827a57549950901e90.png" kopiert.

Unten ist meine Projektstruktur: Geben Sie hier die Bildbeschreibung ein

Ein weiteres Problem ist, dass ich den folgenden Code zum Importieren dieser Bilddatei verwendet habe, diese jedoch nicht im Browser angezeigt wird. Wenn ich die URL 'public / icons / imageview_item_normal.png' für das img-Tag verwende, funktioniert dies einwandfrei. Wie verwende ich das aus der Bilddatei importierte Objekt?

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
quelle
1
Haben Sie versucht, den URL-Loader zu entfernen?
Jaime
Ich habe den URL-Loader aus der Webpack-Konfigurationsdatei entfernt und das Verzeichnis dist entfernt und den Befehl webpack erneut ausgeführt. Das Problem ist immer noch vorhanden. Die Datei wurde generiert.
Joey Yi Zhao

Antworten:

196

In Bezug auf Problem Nr. 1

Sobald Sie den File-Loader in der webpack.config konfiguriert haben, testet er bei jeder Verwendung von import / require den Pfad für alle Loader. Falls eine Übereinstimmung vorliegt, wird der Inhalt durch diesen Loader geleitet. In Ihrem Fall stimmte es überein

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

und deshalb sehen Sie das Bild emittiert an

dist/public/icons/imageview_item_normal.png

Welches ist das gewünschte Verhalten.

Der Grund, warum Sie auch den Namen der Hash-Datei erhalten, ist, dass Sie einen zusätzlichen Inline-File-Loader hinzufügen. Sie importieren das Bild als:

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

Durch das Präfixieren file!wird die Datei erneut an den Dateilader übergeben, und diesmal hat sie keine Namenskonfiguration.

Ihr Import sollte also wirklich nur sein:

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

Aktualisieren

Wie von @cgatian angegeben, können Sie dem Import zwei Ausrufezeichen (!!) voranstellen, wenn Sie tatsächlich einen Inline-Dateilader verwenden möchten, ohne die globale Konfiguration des Webpacks zu beachten:

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

In Bezug auf Problem Nr. 2

Nach dem Importieren des PNG enthält die imgVariable nur den Pfad, den der Dateilader "kennt", nämlich public/icons/[name].[ext](aka "file-loader? name=/public/icons/[name].[ext]"). Ihr Ausgabeverzeichnis "dist" ist unbekannt. Sie können dies auf zwei Arten lösen:

  1. Führen Sie Ihren gesamten Code im Ordner "dist" aus
  2. Fügen Sie publicPathIhrer Ausgabekonfiguration eine Eigenschaft hinzu, die auf Ihr Ausgabeverzeichnis verweist (in Ihrem Fall ./dist).

Beispiel:

output: {
  path: PATHS.build,
  filename: 'app.bundle.js',
  publicPath: PATHS.build
},
omerts
quelle
152
Dies ist das einzige Dokument im gesamten Internet, das besagt, dass "publicPath" die vom Dateilader verwendete URL ändert.
Tyler Jones
@ TylerJones was meinst du?
Sagiv bg
1
@ Sag1v, ich denke, es ist besser für Sie, eine neue Frage zu posten, mit mehr Informationen einschließlich Ihrer Webpack-Konfiguration
omerts
1
Nur um die Antwort zu ergänzen. (Bitte bearbeiten, da ich denke, dass dies nützlich ist.) Wenn Sie sich in einer Situation befinden, in der Sie die Webpack-Konfiguration auf einer require-Anweisung umgehen möchten, können Sie vor dem Import zwei zusätzliche Pony hinzufügenrequire('!!file-loader!wenis.png');
cgatian
2
Die Dokumentation wurde seit den oben genannten Behauptungen erheblich verbessert :) - Siehe: github.com/webpack-contrib/file-loader#options und weitere Informationen zu publicPath: github.com/webpack-contrib/file-loader#publicpath
Pavelloz
15

Ich hatte ein Problem beim Hochladen von Bildern in mein React JS-Projekt. Ich habe versucht, die Bilder mit dem File-Loader zu laden. Ich habe auch Babel-Loader in meiner Reaktion verwendet.

Ich habe die folgenden Einstellungen im Webpack verwendet:

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

Dies half beim Laden meiner Bilder, aber die geladenen Bilder waren irgendwie beschädigt. Nach einigen Recherchen stellte ich dann fest, dass der File-Loader die Bilder beschädigt, wenn der Babel-Loader installiert ist.

Um das Problem zu umgehen, habe ich versucht, einen URL-Loader zu verwenden, der für mich perfekt funktioniert.

Ich habe mein Webpack mit den folgenden Einstellungen aktualisiert

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

Ich habe dann den folgenden Befehl verwendet, um die Bilder zu importieren

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

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

Installieren Sie zuerst den File Loader:

$ npm install file-loader --save-dev

Fügen Sie diese Regel in webpack.config.js hinzu

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

Alternativ können Sie das gleiche wie schreiben

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

und dann einfachen Import verwenden

import varName from 'relative path';

und in jsx schreibe gerne <img src={varName} ..../>

.... sind für andere Bildattribute

Gaurav Paliwal
quelle
1
Dieser Endteil ist sehr wichtig für Bilder, die von jsx dank @ gaurav-paliwal eingefügt wurden. Die Verwendung von import imgPath half mir bei der Lösung und die Bilder wurden in den Ordner dist / build kopiert
Ebrahim
1
Mit diesem outputPathSchlüssel konnte ich herausfinden, wo Dateien mit Unterordnern abgelegt werden sollen. Die anderen Antworten hier haben nicht funktioniert. Vielen Dank.
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} />
Янов Алексей
quelle
0

Dies ist mein Arbeitsbeispiel für unsere einfache Vue-Komponente.

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