Cách tải tệp hình ảnh bằng trình tải tệp webpack


141

Tôi đang sử dụng webpack để quản lý một dự án Reacjs . Tôi muốn tải hình ảnh trong javascript bằng webpack file-loader. Dưới đây là 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
        }
    }
}

Tôi đã sử dụng dòng này để tải các tệp hình ảnh và sao chép chúng vào thư mục dist / public / icon và giữ nguyên tên tệp.

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

Nhưng tôi có hai vấn đề khi sử dụng nó. Khi tôi chạy webpacklệnh, tệp hình ảnh đã được sao chép vào thư mục dist / public / icon / như mong đợi. Tuy nhiên, nó cũng được sao chép vào thư mục dist với tên tệp này "df55075baa16f3827a57549950901e90.png".

Dưới đây là cấu trúc dự án của tôi: nhập mô tả hình ảnh ở đây

Một vấn đề khác là tôi đã sử dụng mã bên dưới để nhập tệp hình ảnh này nhưng nó không hiển thị trên trình duyệt. Nếu tôi đang sử dụng url 'public / icon / fanteview_item_n normal.png' trên thẻ img, nó hoạt động tốt. Làm thế nào để sử dụng đối tượng được nhập từ tệp hình ảnh?

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
Bạn đã thử loại bỏ trình tải url chưa?
Jaime

Tôi đã gỡ bỏ trình tải url khỏi tệp cấu hình webpack và xóa thư mục dist và chạy lại lệnh webpack, vấn đề vẫn còn đó. Các tập tin đã được tạo ra.
Joey Yi Zhao

Câu trả lời:


196

Về vấn đề # 1

Khi bạn đã cấu hình trình tải tệp trong webpack.config, bất cứ khi nào bạn sử dụng nhập / yêu cầu, nó sẽ kiểm tra đường dẫn đối với tất cả các trình tải và trong trường hợp có kết quả khớp, nó sẽ chuyển nội dung qua trình tải đó. Trong trường hợp của bạn, nó phù hợp

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

và do đó bạn thấy hình ảnh phát ra

dist/public/icons/imageview_item_normal.png

đó là hành vi mong muốn.

Lý do bạn cũng nhận được tên tệp băm là bởi vì bạn đang thêm một trình tải tệp nội tuyến bổ sung. Bạn đang nhập hình ảnh dưới dạng:

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

Tiền tố với file!, chuyển tệp vào trình tải tệp một lần nữa và lần này nó không có cấu hình tên.

Vì vậy, nhập khẩu của bạn nên thực sự chỉ là:

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

Cập nhật

Như @cgatian đã lưu ý, nếu bạn thực sự muốn sử dụng trình tải tệp nội tuyến, bỏ qua cấu hình toàn cầu của gói webpack, bạn có thể thêm tiền tố nhập với hai dấu chấm than (!!):

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

Về vấn đề # 2

Sau khi nhập png, imgbiến chỉ giữ đường dẫn trình tải tệp "biết về", đó là public/icons/[name].[ext](aka "file-loader? name=/public/icons/[name].[ext]"). Thư mục đầu ra của bạn "dist" không xác định. Bạn có thể giải quyết điều này theo hai cách:

  1. Chạy tất cả mã của bạn trong thư mục "dist"
  2. Thêm thuộc publicPathtính vào cấu hình đầu ra của bạn, trỏ đến thư mục đầu ra của bạn (trong trường hợp của bạn ./dist).

Thí dụ:

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

152
Đây là tài liệu duy nhất trên INTERNET ENTIRE có nội dung "publicPath" sẽ thay đổi url được sử dụng bởi trình tải tập tin.
Tyler Jones

@TylerJones có nghĩa là gì?
Sagiv bg

1
@ Sag1v, tôi nghĩ sẽ tốt hơn nếu bạn đăng một câu hỏi mới, với nhiều thông tin hơn bao gồm cả cấu hình webpack của bạn
bỏ qua

1
Chỉ để thêm vào câu trả lời. (xin vui lòng chỉnh sửa như tôi nghĩ rằng đây là hữu ích) Bạn nếu bạn thấy mình trong một tình huống mà bạn muốn bỏ qua cấu hình webpack trên yêu cầu tuyên bố bạn có thể thêm hai tiếng nổ bổ sung trước khi nhập khẩurequire('!!file-loader!wenis.png');
cgatian

2
Tài liệu đã được cải thiện rất nhiều kể từ khi tuyên bố ở trên :) - Xem: github.com/webpack-contrib/file-loader#options và biết thêm về publicPath: github.com/webpack-contrib/file-loader#publicpath
Pavelloz

15

Tôi gặp sự cố khi tải hình ảnh lên dự án React JS của mình. Tôi đã cố gắng sử dụng trình tải tập tin để tải hình ảnh; Tôi cũng đang sử dụng Babel-loader trong phản ứng của mình.

Tôi đã sử dụng các cài đặt sau trong gói web:

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

Điều này giúp tải hình ảnh của tôi, nhưng hình ảnh được tải là loại bị hỏng. Sau đó, sau một số nghiên cứu, tôi biết rằng trình tải tệp có lỗi làm hỏng hình ảnh khi cài đặt trình tải babel.

Do đó, để khắc phục sự cố tôi đã cố gắng sử dụng trình tải URL hoạt động hoàn hảo cho tôi.

Tôi đã cập nhật gói web của mình với các cài đặt sau

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

Sau đó tôi đã sử dụng lệnh sau để nhập hình ảnh

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

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

6

Cài đặt trình tải tập tin trước:

$ npm install file-loader --save-dev

Và thêm quy tắc này trong webpack.config.js

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

5

Ngoài ra, bạn có thể viết giống như

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

và sau đó sử dụng nhập đơn giản

import varName from 'relative path';

và trong jsx viết như <img src={varName} ..../>

.... dành cho các thuộc tính hình ảnh khác


1
Phần cuối này rất quan trọng đối với hình ảnh được chèn bởi jsx cảm ơn @ gaurav-paliwal. bằng cách sử dụng nhập imgPath đã giúp tôi giải quyết nó và các hình ảnh được sao chép vào thư mục dist / build
Ebrahim

1
outputPathChìa khóa đó đã giúp tôi tìm ra nơi đặt các tệp với các thư mục con và tất cả những thứ đó. Các câu trả lời khác ở đây không hoạt động. Cảm ơn rất nhiều.
Thielicy

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

Đây là ví dụ làm việc của tôi về thành phần Vue đơn giản của chúng tôi.

<template functional>
    <div v-html="require('!!html-loader!./../svg/logo.svg')"></div>
</template>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.