U P D A T E D Fixed code in the repository
first of all i know there are like some posts about this topic, but they are so outdated (webpack 1 or 2)
I'm trying to setup a webpack config for React images avoiding the ugly var myImage = require('./imagePath/image.jpg');
It works only if i add an image via scss or css (background image i.e.),but if i try to add image in the index.html or in a react component they are not generated.
I'm trying to use file-loader, html-loader and transform-react-jsx-img-import
I created this repository, with the sample case.
You can clone it and just install dependencies via npm install
or yarn install
I have been struggling with this the last 2 days, so any help would be much appreciated.
const autoprefixer = require('autoprefixer'),
DashboardPlugin = require('webpack-dashboard/plugin'),
ExtractTextPlugin = require('extract-text-webpack-plugin'),
HtmlPlugin = require('html-webpack-plugin'),
path = require('path'),
webpack = require('webpack');
const isProd = process.env.NODE_ENV === 'production';
//////////////////////// FILEPATH ///////////////////////
/////////////////////////////////////////////////////////
const buildFolder = 'dist';
const PATHS = {
src : path.resolve(__dirname, 'src'),
build : path.resolve(__dirname, buildFolder),
appJS : path.resolve(__dirname, 'src/app.js'),
indexHTML : path.resolve(__dirname, 'src/index.html')
}
//////////////////////// PLUGINS ////////////////////////
/////////////////////////////////////////////////////////
const HtmlPluginOptions = {
template: PATHS.indexHTML,
minify: {
collapseWhitespace: true
},
hash: true
};
const ExtractTextPluginOptions = {
filename: '[name].bundle.css',
disable: !isProd,
allChunks: true,
ignoreOrder: false
}
const devServerOptions = {
contentBase: PATHS.build,
compress: true,
port: 6969,
stats: 'errors-only',
open: true,
hot: true,
openPage: ''
};
const pluginsDev = [
new DashboardPlugin(),
autoprefixer,
new HtmlPlugin(HtmlPluginOptions),
new ExtractTextPlugin(ExtractTextPluginOptions),
new webpack.HotModuleReplacementPlugin()
];
const pluginsProd = [
require('autoprefixer'),
new HtmlPlugin(HtmlPluginOptions),
new ExtractTextPlugin(ExtractTextPluginOptions)
];
var pluginsList = isProd ? pluginsProd : pluginsDev;
//////////////////////// LOADERS ////////////////////////
/////////////////////////////////////////////////////////
const postcss = {
loader: 'postcss-loader',
options: {
sourceMap: 'inline',
plugins() {
return [autoprefixer({ browsers: 'last 3 versions' })];
}
}
};
const stylesDev = ['style-loader', 'css-loader?sourceMap', postcss, 'sass-loader?sourceMap'];
const stylesProd = ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', postcss, 'sass-loader'],
publicPath: buildFolder
});
const styles = {
test: /\.scss$/,
use: isProd ? stylesProd : stylesDev
};
const javascript = {
test: /\.(js|jsx)$/,
use: 'babel-loader',
exclude: /node_modules/
}
const images = {
test: /\.(jpe?g|svg|png|gif)$/i,
use: [
'file-loader?name=assets/img/[name].[ext]'
]
}
const html = {
test: /\.(html)$/,
use: {
loader: 'html-loader',
options: {
attrs: ['img:src', 'link:href']
}
}
}
//////////////////////// WEBPACK ////////////////////////
/////////////////////////////////////////////////////////
const webpackConfig = {
entry: {
app: PATHS.appJS
},
output: {
path: PATHS.build,
filename: '[name].bundle.js'
},
module: {
rules: [javascript, styles, images, html]
},
devServer: devServerOptions,
plugins: pluginsList
}
module.exports = webpackConfig;
There are a ./src/index.html file with an <img>
tag
and also ./src/components/App.js file with another <img>
tag
Again, thanks in advance. Remember that you have the full example in this repository, try got to show both logos (webpack and react logo)
URLs starting with a /
are not transformed by html-loader
(see 'Root-relative' URLs). Most loaders follow this behaviour, because that allows you to use existing files that use files on the server, that were not processed with webpack. Additionally, if it interpreted the URL as a path (like in any JavaScript module), it would look in the root of your file system and that's not what you want here.
As you did it in you SCSS, you have to use a relative path.
<img src="./public/assets/img/logo--webpack.svg" alt="Logo Webpack"/>
In a React component you cannot use the html-loader
because you're not actually writing HTML, but JSX, which is syntactic sugar that will be transformed into function calls. For details see JSX In Depth.
That means you'll have to import the image and pass it to the src
attribute.
import reactLogo from '../public/assets/img/logo--react.svg';
<img src={reactLogo} alt="Logo React"/>
You could probably use a Babel plugin to transform <img>
tags and automatically add imports of the sources. From a quick search, I found babel-plugin-transform-react-jsx-img-import, although I don't know whether that works as it doesn't seem to be maintained.