Webpack moves images regardless it component nested routes - image

I am using components with <img src> inside routes.
import myImg from './img.png'
<img src={myImg}>
Webpacks build move all files to thedist` folder, including images from components.
The problem is it moves images to the root of dist e.g. dist/img.png.
But also webpack rewrite images paths in HTML with component routes e.g.
<img src="/path/img.png">.
It bring all images from nested routes to 404.
I need to force webpack move images accordingly its routes or write src path in HTML without routes.
How should I do that?
router
const router = (
<BrowserRouter>
<Route path='/'
component={App}/>
</BrowserRouter>
);
ReactDOM.render(
router,
document.getElementById('root')
);
webpack.config.js
module.exports = {
watch : true,
entry : {
app: [
'babel-polyfill',
path.resolve(__dirname, 'src/index.jsx')
]
},
resolve: {
extensions: ['.js', '.jsx']
},
output : {
filename: 'bundle-[hash].js',
path : path.resolve(__dirname, 'dist'),
},
plugins: [
new ExtractTextPlugin('[name]-[hash].css'),
],
module : {
rules: [
{
test : /\.jsx?$/,
exclude: /node_modules/,
use : 'babel-loader',
include: path.join(__dirname, 'src')
},
{
test: /\.(less|css)$/,
use : ExtractTextPlugin.extract(
{
use: [
{loader: 'css-loader'},
{loader: 'resolve-url-loader'},
{loader: 'less-loader'},
]
}
),
},
{
test: /\.(png|jpg|jpeg|gif)$/,
use : [
'file-loader?hash=sha512&digest=hex&name=[name]-[hash].[ext]',
'image-webpack-loader?bypassOnDebug&optimizationLevel=7&interlaced=false'
],
},
]
}
}

Related

Name is getting mangled by Webpack 5 while mini-css-extract-plugin loader

Trying to export scss file with bootstrap 5.2 to a css file and linking that file to a index.php file but class names i guess are getting mangled somehow so I can't use bootstrap class like for a button btn btn-primary, as the generated classes names are like GcpZ2uTclIsK3IUwa3qT XWJXtmqteXQMN_oydssO
I have tried many webpack config but unable to find a solution. My current configs are shared below.
how can I use bootstrap exported scss in webpack build ?
webpack.config.js
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
mode: "development",
devtool: "source-map",
entry: "./src/js/main.js",
output: {
filename: "main.js",
path: path.resolve(__dirname, "dist"),
},
plugins: [
new MiniCssExtractPlugin({
linkType: "text/css",
}),
],
module: {
rules: [
{
test: /\.scss$/,
use: [
{ loader: MiniCssExtractPlugin.loader },
{
loader: "css-loader",
options: {
modules: true,
},
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: () => [require("autoprefixer")],
},
},
},
{
loader: "sass-loader",
},
],
},
],
},
};
styles.scss
#import "~bootstrap/scss/bootstrap";
main.js
import "../scss/styles.scss";
import * as bootstrap from 'bootstrap'
import {addNumber} from './sum'
import {divideNumbers} from './division'
import {buttonClickAction} from './events'
I'm so new to webpack so I didn't exactly know what was I doing wrong.
The problem was in webpack config file css-loader as bootstrap works with global css selector not module based i had to remove
{
options: {
modules: true,
},
},

How to use preload webpack plugin with blade templates

So i have a laravel/vuejs app , i'm trying to preload the css chunks that i have generated upon splitting components, it works fine but it generates an index.html. Is it possible to somehow do it in blade templates? What could be the solution?
Here is my webpack.config.js
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const {VueLoaderPlugin} = require("vue-loader");
const PreloadWebpackPlugin = require('preload-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const path = require("path");
module.exports = {
entry: {
main: "./resources/js/app.js",
},
output: {
publicPath: '/',
path: path.resolve(__dirname, "public"),
},
plugins: [
new HtmlWebpackPlugin(),
new VuetifyLoaderPlugin(),
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: `components/[name].css`
}),
new PreloadWebpackPlugin({
rel: 'preload',
include: 'asyncChunks', // can be 'allChunks' or 'initial' or see more on npm page
fileBlacklist: [/\.map|.js/], // here may be chunks that you don't want to have preloaded
})
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
"css-loader"
]
},
{
test: /\.js$/,
loader: 'babel-loader',
},
{
test: /\.s[ac]ss$/i,
use: [
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
'sass-loader',
],
},
{
test: /\.vue$/,
loader: "vue-loader",
options: {
extractCSS: true
}
},
],
},
resolve: {
extensions: ['.js', '.vue'],
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/](vue|axios|jquery|bootstrap)[\\/]/,
name: 'vendor',
chunks: 'all'
}
}
}
}
}
And one final question , is it better to preload/prefetch the js chunks too? ( to optimize the performance )

Local image not loading in React [duplicate]

This question already has answers here:
Images not loading in React
(3 answers)
Closed 2 years ago.
Very new to storing local assets on React.
I've configured webpack with file-loader and image-loader and stored the images locally, but for some reason it doesn't seem to be showing:
import React, { Component } from 'react';
import WorkItem from './work-item';
import WorkItemsArray from './work-items-array';
class Work extends Component {
render() {
return (
<div id='work'>
<h1>Work</h1>
<img src={require('../images/weatherImg.png')}/>
<div id='portfolio'>
{WorkItemsArray.map(({ url, img, title, description, github }) => {
return (
<WorkItem
key={title}
url={url}
img={img}
title={title}
description={description}
github={github}
/>
);
})}
</div>
</div>
);
}
}
export default Work;
webpack.config.js
var webpack = require('webpack');
module.exports = {
entry: [
'./src/index.js'
],
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: [/\.css$/, /\.scss$/],
exclude: /node_modules/,
loaders: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /.*\.(gif|png|jpe?g|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
name: 'images/[name]_[hash:7].[ext]'
}
}
]
},
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
quality: 65
},
// optipng.enabled: false will disable optipng
optipng: {
enabled: false,
},
pngquant: {
quality: '65-90',
speed: 4
},
gifsicle: {
interlaced: false,
},
// the webp option will enable WEBP
webp: {
quality: 75
}
}
}
]
}
]
},
resolve: {
extensions: ['*', '.js', '.jsx']
},
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: 'bundle.js'
},
devServer: {
contentBase: './dist',
historyApiFallback: true
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
]
};
FWIW, I'm not getting any errors at all, just that the image doesn't seem to be loading.
Any help greatly appreciated!
Since you assumed you didn't get any error, you have two possibilities: -
Either the image is not visible (maybe because of height and width are small)
Or the whole component <Work /> is not rendered, or even rendered, it is then unmounted without detecting the same.
For the first, force a specific size to the image or replace another image: -
<img src={require('../images/weatherImg.png')} width="400" height="500"/>
For the second, add a componentDidMount and componentWillUnmount and debug, then check the browser console: -
class Work extends Component {
componentDidMount() {
console.log(new Date(), ' Work is mouned 🙃');
}
componentWillUnmount() {
console.log(new Date(), ' Work will be killed 😭');
}
render() {
//...
}
}
let's say you have your images folder inside the public folder.
try:
<img src={require(process.env.PUBLIC_URL + "/images/dog.png")}
for others, if you aren't using webpack try:
<img src={process.env.PUBLIC_URL + "/images/dog.png"}

Webpack dev server live reload with proxy

I'm running a PHP app at localhost:8000.
I want to use webpack-dev-server to hot reload css, react and js components.
Had set a proxy to http://localhost:8000 but webpack-dev-server isn't reloading the browser.
Here's the webpack.config.js:
var path = require( 'path' );
var autoprefixer = require( 'autoprefixer' );
module.exports = {
entry: [
'./src/app.js'
],
output: {
path: path.join( __dirname, 'dist' ),
publicPath: 'http://localhost:8000',
filename: 'app.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loaders: [ 'react-hot', 'babel-loader' ]
},
{
test: /\.scss$/,
loaders: [ 'style-loader', 'css-loader', 'sass-loader' ]
}
]
},
postcss: [
autoprefixer(
{
browsers: [
'last 2 versions'
]
}
)
],
devServer: {
port: 3000,
proxy: {
'**': {
target: 'http://localhost:8000',
secure: false,
changeOrigin: true
}
}
}
}
I'm accessing the webpack-dev-server at http://localhost:3000/webpack-dev-server/.
Changing my react component does cause webpack-dev-server to recompile, but the browser doesn't update.
Running webpack does compile the dist/app.js file, as calling it manually and reloading the browser works.
So my publicPath was wrong.
Here's the fix:
output: {
path: path.join( __dirname, 'dist' ),
publicPath: 'http://localhost:3000/dist/',
filename: 'app.js'
},
update: But it seems to be reloading the browser ¯_(ツ)_/¯

React & Webpack: Loading and displaying images as background-image

I'm creating a banner-like component with image set as a component's background but I can't get it to work. I tried different suggestions posted online to no luck and at the moment I'm not sure whether my mistake is within react code or it's the webpack that doesn't load the files correctly.
Here's my file structure:
AppFolder
- client/
-- components/
-- data/
-- images/
----- banners/
------- frontPageBanner2.png
-------
-- styles/
-- myApp.js
-- store.js
---------
- index.html
- package.json
- webpack.config.dev.js
Here's my webpack configuration:
var path = require('path');
var webpack = require('webpack');
module.exports = {
devtool: 'source-map',
entry: [
'webpack-hot-middleware/client',
'./client/myApp'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/static/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
module: {
loaders: [
// js
{
test: /\.js$/,
exclude: /node_modules/,
loaders: ['babel'],
presets: ['es2015', 'react'],
include: path.join(__dirname, 'client')
},
// CSS
{
test: /\.scss$/,
include: path.join(__dirname, 'client'),
loader: 'style-loader!css-loader!sass-loader'
},
// PNG
{
test: /\.(jpg|png)$/,
loader: "url-loader?limit=25000",
//loader: 'file?name=[path][name].[ext]',
include: path.join(__dirname, 'client')
},
// FontAwesome
{ 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])?$/,
exclude: path.join(__dirname, 'client/images'),
loader: "file-loader" },
// other SVG
{ test: /\.svg$/,
loader: 'url-loader',
query: { mimetype: "image/svg+xml" },
include: path.join(__dirname, 'client/images')
},
]
}
};
And here's how I'm using it in the app:
export class Banner extends React.Component {
render() {
console.log(this.props.banners);
// = '../images/banners/frontPageBanner.png'
const bannerImg = this.props.image.backgroundImage;
var bannerStyle = {
background: 'url(' + bannerImg + ')',
backgroundSize: this.props.image.backgroundSize,
backgroundPosition: this.props.image.backgroundPosition,
}
return (
<section key={this.props.key} className="container hero" style={bannerStyle}>
<div className="textbox">
<h2>{this.props.title}</h2>
</div>
</section>
)
}
}
Here's resulting html:
<section class="container hero" style="background: url('../images/banners/frontPageBanner2.png') 100% 100% / contain;">
...
</section>
but no image is displayed. Also opening the image src link shows just a blank screen. Why? And how can i fix it?
You should pass a var that is the result of requiring the image, when you require it using webpack, it'll generate a base64 inline image, not a relative path.
var DuckImage = require('./Duck.jpg');
var bannerStyle = {
backgroundImage: 'url(' + DuckImage + ')',
backgroundSize: this.props.image.backgroundSize,
backgroundPosition: this.props.image.backgroundPosition,
}

Resources