Webpack & React. Loaded image can't resolve path 404 - reactjs

At this case I am trying to set up sort of high-order component and further implement 'dynamic' image loads for it. Can you please explain what has been done wrong in order to reference to the inside the component.
React Component
class Slide extends Component {
constructor(props) {
super(props)
}
render () {
let imageLeft = {
backgroundImage: 'url(./assets/introleft.png)'
}
return (
<div className={styles.someStyles}>
<div className={styles.someStyles} style={imageLeft} > </div>
</div>
)
}
}
... state
export default connect(mapStateToProps)(Slide);
Project structure
Webpack config
const path = require('path'),
webpack = require('webpack'),
HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'./index.js'
],
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'build'),
publicPath: '/'
},
context: path.resolve(__dirname, 'logic'),
devtool: 'inline-source-map',
devServer: {
hot: true,
contentBase: path.resolve(__dirname, 'build'),
publicPath: '/'
},
module: {
rules: [
{
test: /\.js$/,
use: [
'babel-loader',
],
exclude: /node_modules/
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader?modules',
'postcss-loader',
],
},{
test: /\.png$/,
use: { loader: 'url-loader', options: { limit: 15000 } },
},
{
test: /\.svg$/,
use: {
loader: 'svg-url-loader',
options: {}
}
],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
new HtmlWebpackPlugin({
template: './index.template.html'
})<script> tag
],
};
P.S: Project has no node.js server, just wepback-dev. So react-router uses hash history /#, wounder if it somehow affects the webpack publicPath property.

When you're using backgroundImage: 'url(./assets/introleft.png)', this will be inserted as is (it's just a string), so your url-loader won't be applied to it. Instead you should import the image:
import introleft from './assets/introleft.png';
Webpack will have applied the url-loader and you get back either the data URL or the URL to the extracted image, if the size was too big. All you need to do now is put that URL into your backgroundImage:
backgroundImage: `url(${introleft})`

Related

Adding TypeScript to exsisting React Project (Not create-react-app)

I have been looking everywhere for a place to tell me how to add tsx compilers to an existing react project. This was not a create-react-app. Is it possible to use both TSX and JSX files in the same project? I don't want to do everything in TSX, but I definitely want to get some practice in and don't want to convert the whole thing. Do you guys have any places I can go look for this? Here is my webpack.config for reference (if you know a way I can add lmk)
Version: "react": "^16.8.1",
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
devtool: 'inline-source-map',
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: "./index.html"
}),
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "/static/cs/styles.css",
chunkFilename: "styles.css"
})
],
entry: './src/index.js',
output: {
path: path.join(__dirname, 'build'),
filename: 'static/js/bundle.js'
},
module: {
rules: [
{
test: /\.s?css$/,
use: [
"style-loader",
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
},
{
use: { loader: 'babel-loader' },
test: /\.js$/,
exclude: /node_modules/
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: '',
},
}
]
},
]
},
devServer: {
contentBase: path.join(__dirname, 'build'),
},
}

Images not showing up in routing / react build vs Dev

Im trying to get my images to appear in my build version of my react code.
```import reportIcon from "../../../../../src/img/reportmanager.svg";
<img src={reportIcon } className="img-icons-list" />```
this code works when I am in build version. My reportmanager icon shows up, but when I navigate to www.mywebsite.com/reports/user -- the icon disappears
import reportIcon from "/src/img/reportmanager.svg";
does not work either. here is my webpack.config.js file
```const HtmlWebPackPlugin = require("html-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname + '/public'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env',
'#babel/react', {
'plugins': ['#babel/plugin-proposal-class-properties']
}]
},
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},
{
test: /\.(eot|ttf|woff|woff2)$/,
loader: 'file-loader?name=./font/[name]_[hash:7].[ext]'
},
{
test: /\.(jpg|png|svg)$/,
loader: 'file-loader?name=./img/[name]_[hash:7].[ext]'
}
]
},
devServer: {
historyApiFallback: {
index: "/",
}
},
plugins: [
new ExtractTextPlugin("css/style.css"),
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
function () {
this.plugin("done", function (stats) {
if (stats.compilation.errors && stats.compilation.errors.length && process.argv.indexOf('--watch') == -1) {
console.log(stats.compilation.errors);
process.exit(1); // or throw new Error('webpack build failed.');
}
// ...
});
}
]
};
I needed to put
<base href="/">
in the index.html of my react project.

Images are loaded in external library, how to load them with webpack?

first and foremost I need to say that I know little of fundamentals of Webpack, and this is probably why I can't find a solution.
So I know in order to load images I need to require a path instead of just typing it as a string require('path/to/image')
Then I got an external library where I need to pass a path property, where lay multiple images. It doesn't seem to work, so how can I load them into my website?
<CountrySelect
multi={false}
flagImagePath="../../../public/flags/" //folder with multiple images
/>
Webpack config:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const outputDirectory = 'dist';
module.exports = {
entry: './src/client/index.js',
output: {
path: path.join(__dirname, outputDirectory),
filename: 'bundle.js',
publicPath: '/',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|woff|woff2|eot|ttf|svg|jpg|jpeg)$/,
loader: 'url-loader?limit=100000'
}
]
},
devServer: {
historyApiFallback: true,
port: 3000,
open: true,
proxy: {
'/api': 'http://localhost:8080'
}
},
plugins: [
new CleanWebpackPlugin([outputDirectory]),
new HtmlWebpackPlugin({
template: './public/index.html',
favicon: './public/favicon.ico'
})
]
};
image-webpack-loader - automatically reduces/compress the bigger image.
url-loader - if image size is small it will included as part of bundle.js otherwise separate directory is created and images are placed inside of it.
npm install --save-dev image-webpack-loader url-loader file-loader
webpack.config.js
const config = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'bundle.js',
publicPath: 'build/' //This is important to load your images.
},
module: {
rules: [
{
test: /\.js$/,
use: [
{ loader: 'babel-loader' },
]
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
{
loader: 'url-loader',
options: { limit: 40000 } //if image of size lessthan 40kb include it in bundle.js
},
'image-webpack-loader'
]
}
]
}
}
Sample Code.
import big from '../images/big.jpg';
import small from '../images/small.png';
const image = document.createElement('img');
image.src = small;
document.body.appendChild(image);
const bigimage = document.createElement('img');
bigimage.src = big;
document.body.appendChild(bigimage);
you can learn more about webpack from Handling Images with Webpack.
I solved the problem by using CopyWebpackPlugin.
plugins: [
new CleanWebpackPlugin([outputDirectory]),
new HtmlWebpackPlugin({
template: './public/index.html',
favicon: './public/favicon.png'
}),
new CopyWebpackPlugin([{ from: './public/flags', to: 'flags', toType: 'dir'
}]),
]
and in CountrySelect:
flagImagePath="/flags/"
So that in the time of production, where static directory is dist, flags are derived from dist directory.

Handling assets with webpack within ReactJs application

I need to load an image in my React component :
webpack.config.js
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const bundleOutputDir = './wwwroot/dist';
module.exports = (env) => {
const isDevBuild = !(env && env.prod);
return [{
stats: { modules: false },
entry: { 'main': './ClientApp/boot.tsx' },
resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx'] },
output: {
path: path.join(__dirname, bundleOutputDir),
filename: '[name].js',
publicPath: 'dist/'
},
module: {
rules: [
{ test: /\.tsx?$/, include: /ClientApp/, use: 'awesome-typescript-loader?silent=true' },
{ test: /\.css$/, use: isDevBuild ? ['style-loader', 'css-loader'] : ExtractTextPlugin.extract({ use: 'css-loader?minimize' }) },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, loader: 'file-loader' },
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader" }
]
},
plugins: [
new CheckerPlugin(),
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./wwwroot/dist/vendor-manifest.json')
})
].concat(isDevBuild ? [
// Plugins that apply in development builds only
new webpack.SourceMapDevToolPlugin({
filename: '[file].map', // Remove this line if you prefer inline source maps
moduleFilenameTemplate: path.relative(bundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
})
] : [
// Plugins that apply in production builds only
new webpack.optimize.UglifyJsPlugin(),
new ExtractTextPlugin('site.css')
])
}];
};
In the component, I tried to load the image like this :
import Logo from '../css/images/logo.png';
but it did not work !
How can I edit the configure the webpack to handle the assets espacially images?
Thanks,
From your example, I considering your image file is locally stored. Did you created reactjs app using created-react-app or ejected the app.
import Logo from '../css/images/logo.png'
and use like <img src={Logo} className="blue"/>
or <img src={require('../css/images/logo.png')} className="blue"/>

React app looking for bundle.js in component folder not project root

The errors I get below are shown in the console after I refresh on a nested route (register/email-confirmation). Whereas non-nested routes do not get this error.
I think the main problem is that it's searching for bundle.js and the image in the nested route path, as opposed to the root path.
The errors in my console:
GET http://localhost:3002/register/bundle.js net::ERR_ABORTED
Refused to execute script from 'http://localhost:3002/register/bundle.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
GET http://localhost:3002/register/a5e694be93a1c3d22b85658bdc30008b.png 404 (Not Found)
My webpack.config.js:
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const BUILD_PATH = path.resolve( __dirname, "./client/build" );
const SOURCE_PATH = path.resolve( __dirname, "./client/src" );
const PUBLIC_PATH = "/";
...
module.exports = {
devtool: 'eval-source-map',
context: SOURCE_PATH,
entry: ['babel-polyfill', SOURCE_PATH + '/index.jsx'],
module: {
rules: [
{
test: /\.jsx?$/,
exclude: [/node_modules/, /server/],
use: {
loader: 'babel-loader',
options: {
presets: ['env', 'es2015', 'react', 'stage-1', 'stage-0', 'stage-2'],
plugins: [
'transform-decorators-legacy',
'transform-es2015-destructuring',
'transform-es2015-parameters',
'transform-object-rest-spread'
]
}
}
},
{
test: /\.scss$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader"
}, {
loader: "sass-loader"
}]
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {}
}
]
},
],
},
output: {
path: BUILD_PATH,
filename: "bundle.js",
},
devServer: {
compress: true,
port: 3002,
historyApiFallback: true,
contentBase: BUILD_PATH,
publicPath: PUBLIC_PATH,
},
plugins: [
new webpack.DefinePlugin(appConstants),
new HtmlWebpackPlugin({
filename: 'index.html',
template: path.resolve(__dirname, 'client/src/index.html'),
inject: true
}),
],
watch: true,
}
I don't know about this bug, but I highly recommend using fuse-box
fuse-box is the future of the build systems, within few minutes you will be running your project with high speed hot reload and many others utitilites...
check this react example seed, it's incredibly amazing..

Resources