Používám webpack ke správě reactjs projekt. Chci načíst obrázky v javascriptu pomocí webpacku file-loader
. Níže je 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 } } }
Tento řádek jsem použil k načtení obrazových souborů a jejich zkopírování do adresáře dist/public/icons a zachování stejného názvu souboru.
{test: /.(jpe?g|png|gif|svg)$/i, loader: "file-loader?name=/public/icons/[name].[ext]"}
Při používání mám ale dva problémy. Když spustím webpack
byl soubor obrázku zkopírován do dist/public/icons/ adresář podle očekávání. Byl však také zkopírován do dist adresáře s tímto názvem souboru „df55075baa16f3827a57549950901e90.png“.
Níže je struktura mého projektu:
Dalším problémem je, že jsem použil níže uvedený kód k importu tohoto souboru obrázku, ale nezobrazuje se v prohlížeči. Pokud na tagu img používám url „public/icons/imageview_item_normal.png“, funguje to dobře. Jak použít objekt importovaný ze souboru obrázku?
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%', } }
Odpověď
Ohledně problému č. 1
Jakmile máte souborový zavaděč nakonfigurován v souboru webpack.config, kdykoli použijete import/require, otestuje cestu proti všem zavaděčům a v případě shody předá obsah tímto zavaděčem. Ve vašem případě se to shodovalo
{ test: /.(jpe?g|png|gif|svg)$/i, loader: "file-loader?name=/public/icons/[name].[ext]" } // For newer versions of Webpack it should be { test: /.(jpe?g|png|gif|svg)$/i, loader: 'file-loader', options: { name: '/public/icons/[name].[ext]' } }
a proto vidíte obraz vysílaný do
dist/public/icons/imageview_item_normal.png
což je žádoucí chování.
Důvod, proč také získáváte název hash souboru, je ten, že přidáváte další vložený zavaděč souborů. Importujete obrázek jako:
'file!../../public/icons/imageview_item_normal.png'.
Předpona s file!
, předá soubor znovu do zavaděče souborů a tentokrát nemá konfiguraci názvu.
Takže váš import by měl být opravdu jen:
import img from '../../public/icons/imageview_item_normal.png'
Aktualizovat
Jak poznamenal @cgatian, pokud skutečně chcete použít vložený zavaděč souborů a ignorovat globální konfiguraci webpacku, můžete před importem uvést dva vykřičníky (!!):
import '!!file!../../public/icons/imageview_item_normal.png'.
Ohledně problému č. 2
Po importu png se zobrazí img
proměnná obsahuje pouze cestu, o které zavaděč souborů „ví“, což je public/icons/[name].[ext]
(také znám jako "file-loader? name=/public/icons/[name].[ext]"
). Váš výstupní adresář „dist“ je neznámý. Můžete to vyřešit dvěma způsoby:
- Spusťte veškerý kód ve složce „dist“
- Přidejte
publicPath
vlastnost do vaší výstupní konfigurace, která ukazuje na váš výstupní adresář (ve vašem případě ./dist).
Příklad:
output: { path: PATHS.build, filename: 'app.bundle.js', publicPath: PATHS.build },