Jak ładować pliki obrazów za pomocą programu ładującego pliki webpack

141

Używam WebPacka do zarządzania projektem Reactjs . Chcę załadować obrazy w javascript przez webpack file-loader. Poniżej znajduje się plik 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
        }
    }
}

Użyłem tej linii do załadowania plików graficznych i skopiowania ich do katalogu dist / public / icons i zachowania tej samej nazwy pliku.

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

Ale mam dwa problemy podczas korzystania z niego. Kiedy uruchomiłem webpackpolecenie, plik obrazu został skopiowany do katalogu dist / public / icons / zgodnie z oczekiwaniami. Jednak został on również skopiowany do katalogu dist z nazwą „df55075baa16f3827a57549950901e90.png”.

Poniżej znajduje się struktura mojego projektu: wprowadź opis obrazu tutaj

Innym problemem jest to, że użyłem poniższego kodu do zaimportowania tego pliku obrazu, ale nie wyświetla się on w przeglądarce. Jeśli używam adresu URL „public / icons / imageview_item_normal.png” w tagu img, działa dobrze. Jak korzystać z obiektu zaimportowanego z pliku obrazu?

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
źródło
1
Czy próbowałeś usunąć program ładujący url?
Jaime,
Usunąłem program ładujący url z pliku konfiguracyjnego webpacka i usunąłem katalog dist i ponownie uruchomiłem komendę webpacka, problem nadal istnieje. Plik został wygenerowany.
Joey Yi Zhao

Odpowiedzi:

196

Odnośnie problemu nr 1

Po skonfigurowaniu programu ładującego pliki w pliku webpack.config, za każdym razem, gdy używasz funkcji import / wymagaj, testuje ścieżkę ze wszystkimi programami ładującymi, aw przypadku dopasowania przekazuje zawartość przez ten moduł ładujący. W twoim przypadku pasowało

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

i dlatego widzisz emitowany obraz

dist/public/icons/imageview_item_normal.png

które jest pożądanym zachowaniem.

Powodem, dla którego otrzymujesz również nazwę pliku skrótu, jest to, że dodajesz dodatkowy wbudowany program ładujący. Importujesz obraz jako:

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

Przedrostek z file!, przekazuje plik ponownie do programu ładującego pliki i tym razem nie ma on konfiguracji nazwy.

Tak więc import powinien wyglądać tak:

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

Aktualizacja

Jak zauważył @cgatian, jeśli faktycznie chcesz użyć wbudowanego programu ładującego pliki, ignorując globalną konfigurację pakietu webpack, możesz poprzedzić import dwoma wykrzyknikami (!!):

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

Odnośnie problemu nr 2

Po zaimportowaniu png, imgzmienna przechowuje tylko ścieżkę, o której program ładujący pliki „wie”, czyli public/icons/[name].[ext](aka "file-loader? name=/public/icons/[name].[ext]"). Twój katalog wyjściowy „dist” jest nieznany. Możesz rozwiązać to na dwa sposoby:

  1. Uruchom cały kod w folderze „dist”
  2. Dodaj publicPathwłaściwość do konfiguracji wyjściowej, która wskazuje na katalog wyjściowy (w twoim przypadku ./dist).

Przykład:

output: {
  path: PATHS.build,
  filename: 'app.bundle.js',
  publicPath: PATHS.build
},
omerty
źródło
153
JEST TO JEDYNY DOKUMENT W CAŁYM INTERNETIE, który mówi, że „publicPath” zmieni adres URL używany przez program ładujący pliki.
Tyler Jones
@TylerJones co masz na myśli?
Sagiv bg
1
@ Sag1v, myślę, że lepiej będzie, jeśli opublikujesz nowe pytanie, z dodatkowymi informacjami, w tym konfiguracją
pakietu internetowego
1
Wystarczy dodać do odpowiedzi. (edytuj, ponieważ myślę, że jest to przydatne) Jeśli znajdziesz się w sytuacji, w której chcesz ominąć konfigurację require('!!file-loader!wenis.png');
pakietu webpacka
2
Dokumentacja została znacznie ulepszona od czasu powyższych twierdzeń :) - Zobacz: github.com/webpack-contrib/file-loader#options i więcej informacji na publicPath: github.com/webpack-contrib/file-loader#publicpath
Pavelloz
15

Miałem problem z przesyłaniem obrazów do mojego projektu React JS. Próbowałem użyć programu ładującego pliki, aby załadować obrazy; W mojej reakcji również korzystałem z programu ładującego Babel.

Użyłem następujących ustawień w pakiecie internetowym:

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

Pomogło to załadować moje obrazy, ale załadowane obrazy były trochę uszkodzone. Po kilku badaniach dowiedziałem się, że program ładujący pliki ma błąd powodujący uszkodzenie obrazów, gdy jest zainstalowany program ładujący babel.

Dlatego, aby obejść ten problem, próbowałem użyć programu ładującego URL, który działał idealnie dla mnie.

Zaktualizowałem mój pakiet internetowy z następującymi ustawieniami

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

Następnie użyłem następującego polecenia, aby zaimportować obrazy

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

      <img  style={{ width: 300, height: 150 }} src={img} />
</div>
user3717160
źródło
6

Najpierw zainstaluj program ładujący pliki:

$ npm install file-loader --save-dev

I dodaj tę regułę do pliku webpack.config.js

           {
                test: /\.(png|jpg|gif)$/,
                use: [{
                    loader: 'file-loader',
                    options: {}
                }]
            }
Nalan Madheswaran
źródło
5

Alternatywnie możesz napisać to samo jak

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

a następnie użyj prostego importu

import varName from 'relative path';

aw jsx pisz jak <img src={varName} ..../>

.... dotyczą innych atrybutów obrazu

Gaurav Paliwal
źródło
1
Ta część końcowa jest bardzo ważna w przypadku obrazów wstawianych przez jsx dzięki @ gaurav-paliwal. użycie importu imgPath pomogło mi rozwiązać ten problem, a obrazy zostały skopiowane do folderu dist / build
Ebrahim
1
Ten outputPathklucz pomógł mi ustalić, gdzie umieścić pliki z podfolderami i tak dalej. Inne odpowiedzi tutaj nie zadziałały. Wielkie dzięki.
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} />
Янов Алексей
źródło
0

To jest mój roboczy przykład naszego prostego komponentu Vue.

<template functional>
    <div v-html="require('!!html-loader!./../svg/logo.svg')"></div>
</template>
Felix
źródło