Cara memuat file gambar dengan file-loader webpack

148

Saya menggunakan webpack untuk mengelola proyek reactjs . Saya ingin memuat gambar dalam javascript oleh webpack file-loader. Di bawah ini adalah 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
        }
    }
}

Saya menggunakan baris ini untuk memuat file gambar dan menyalinnya ke direktori dist / public / icons dan menyimpan nama file yang sama.

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

Tapi saya punya dua masalah saat menggunakannya. Ketika saya menjalankan webpackperintah, file gambar disalin ke direktori dist / public / icons / seperti yang diharapkan. Namun itu juga disalin ke direktori dist dengan nama file ini "df55075baa16f3827a57549950901e90.png".

Di bawah ini adalah struktur proyek saya: masukkan deskripsi gambar di sini

Masalah lain adalah saya menggunakan kode di bawah ini untuk mengimpor file gambar ini tetapi tidak muncul di browser. Jika saya menggunakan url 'public / icons / imageview_item_normal.png' pada tag img, itu berfungsi dengan baik. Bagaimana cara menggunakan objek yang diimpor dari file gambar?

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
sumber
1
Sudahkah Anda mencoba menghapus url-loader?
Jaime
Saya menghapus url-loader dari file konfigurasi webpack dan menghapus direktori dist dan menjalankan kembali perintah webpack, masalahnya masih ada. File telah dibuat.
Joey Yi Zhao

Jawaban:

203

Mengenai masalah # 1

Setelah Anda memiliki file-loader yang dikonfigurasi di webpack.config, kapan pun Anda menggunakan import / require itu menguji jalur terhadap semua loader, dan jika ada kecocokan, file-loader akan meneruskan konten melalui loader itu. Dalam kasus Anda, itu cocok

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

dan karena itu Anda melihat gambar dipancarkan ke

dist/public/icons/imageview_item_normal.png

yang merupakan perilaku yang diinginkan.

Alasan Anda juga mendapatkan nama file hash, adalah karena Anda menambahkan pemuat file sebaris tambahan. Anda mengimpor gambar sebagai:

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

Mengawali dengan file!, meneruskan file ke file-loader lagi, dan kali ini tidak memiliki konfigurasi nama.

Jadi, impor Anda seharusnya hanya berupa:

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

Memperbarui

Seperti dicatat oleh @cgatian, jika Anda benar-benar ingin menggunakan pemuat file inline, mengabaikan konfigurasi global webpack, Anda dapat mengawali impor dengan dua tanda seru (!!):

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

Mengenai masalah # 2

Setelah mengimpor png, imgvariabel hanya menyimpan jalur yang "diketahui" oleh file-loader, yaitu public/icons/[name].[ext](alias "file-loader? name=/public/icons/[name].[ext]"). Output dir "dist" Anda tidak diketahui. Anda dapat menyelesaikannya dengan dua cara:

  1. Jalankan semua kode Anda di bawah folder "dist"
  2. Tambahkan publicPathproperti ke konfigurasi keluaran Anda, yang mengarah ke direktori keluaran Anda (dalam kasus Anda ./dist).

Contoh:

output: {
  path: PATHS.build,
  filename: 'app.bundle.js',
  publicPath: PATHS.build
},
omerts
sumber
154
INI ADALAH SATU-SATUNYA DOKUMEN DI SELURUH INTERNET yang mengatakan "publicPath" akan mengubah url yang digunakan oleh file loader.
Tyler Jones
@TylerJones apa maksudmu?
Sagiv bg
1
@ Sag1v, saya pikir lebih baik bagi Anda untuk mengirim pertanyaan baru, dengan informasi lebih lanjut termasuk konfigurasi webpack Anda
omerts
1
Hanya untuk menambah jawaban. (harap edit karena menurut saya ini berguna) Anda jika Anda berada dalam situasi di mana Anda ingin melewati konfigurasi webpack pada pernyataan yang dibutuhkan, Anda dapat menambahkan dua poni tambahan sebelum mengimporrequire('!!file-loader!wenis.png');
cgatian
2
Dokumentasi telah sangat ditingkatkan sejak klaim di atas :) - Lihat: github.com/webpack-contrib/file-loader#options dan info lebih lanjut di publicPath: github.com/webpack-contrib/file-loader#publicpath
Pavelloz
16

Saya mengalami masalah saat mengunggah gambar ke proyek React JS saya. Saya mencoba menggunakan file-loader untuk memuat gambar; Saya juga menggunakan Babel-loader dalam reaksi saya.

Saya menggunakan pengaturan berikut di webpack:

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

Ini membantu memuat gambar saya, tetapi gambar yang dimuat agak rusak. Kemudian setelah beberapa penelitian saya mengetahui bahwa file-loader memiliki bug yang merusak gambar ketika babel-loader diinstal.

Oleh karena itu, untuk mengatasi masalah ini saya mencoba menggunakan pemuat URL yang bekerja dengan sempurna untuk saya.

Saya memperbarui paket web saya dengan pengaturan berikut

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

Saya kemudian menggunakan perintah berikut untuk mengimpor gambar

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

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

Instal file loader terlebih dahulu:

$ npm install file-loader --save-dev

Dan tambahkan aturan ini di webpack.config.js

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

Atau Anda bisa menulis seperti itu

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

lalu gunakan impor sederhana

import varName from 'relative path';

dan di jsx tulis seperti <img src={varName} ..../>

.... adalah untuk atribut gambar lainnya

Gaurav Paliwal
sumber
1
Bagian akhir ini sangat penting untuk gambar yang disisipkan oleh jsx thanks @ gaurav-paliwal. menggunakan import imgPath membantu saya menyelesaikannya dan gambar disalin ke folder dist / build
Ebrahim
1
Itu outputPathkunci membantu saya mencari tahu di mana untuk menempatkan file dengan subfolder dan semua itu. Jawaban lain di sini tidak berhasil. Terima kasih banyak.
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} />
Yanov
sumber
0

Ini adalah contoh kerja saya dari komponen Vue sederhana kami.

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