So I just want to use some images in my React application, but images are not loading up. Some images are set up in CSS like that:
background-image: url('/../img/logo.png');
Another way I would like to use images in inside React components with
img tag, how would I go about doing this?
Here is my webpack config:
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = (env) => {
const isProduction = env === 'production';
return {
entry: './src/app.js',
output: {
path: path.resolve(__dirname, 'public', 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
loader: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/
}, {
test: /\.s?css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// you can specify a publicPath here
// by default it use publicPath in webpackOptions.output
publicPath: '../'
}
},
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
}]
},
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "styles.css",
})
],
devtool: isProduction ? 'source-map' : 'inline-source-map',
devServer: {
contentBase: path.resolve(__dirname, 'public'),
historyApiFallback: true,
publicPath: '/dist/'
},
performance: {
hints: process.env.NODE_ENV === 'production' ? "warning" : false
},
}
};
index.html inside public folder:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Kinnisvara ABC</title>
<link rel="stylesheet" href="/dist/styles.css" type="text/css">
</head>
<body>
<div id="app"></div>
<script src="/dist/bundle.js"></script>
</body>
</html>
CSS is loading up, but images are not.
Pictures of my file structure:
Can anyone help me with that, please?
Have 2 way
Use webpack url-loader
Add this line to rules module in webpack file
{ test: /.(png|jpg|woff|woff2|eot|ttf|svg|gif)$/, loader: 'url-loader?limit=1024000' }
Use serve to point image
{
test: /\.(gif|png)$/, //Customise according to your need
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
name: PATH + '.[ext]' //Path will be assets or image path
}
}
]
}
configure url-loader in webpack configuration like this.
You didn't added image loader like css so try to add that
test: /\.(gif|jpe?g|png)$/,
Related
I've just created a template for a webapp using Webpack.
Unfortunatly whenever I'm building the App to dev or Prod, the File-Loader does not fix there references images and it creates empty files.
My config looks like this:
webpack.common.config
// noinspection WebpackConfigHighlighting
const path = require('path');
require('html-webpack-plugin');
module.exports = {
entry: {
vendor: path.join(__dirname, 'Source', 'Vendor.ts'),
main: path.join(__dirname, 'Source', 'Index.tsx')
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: '/node_modules/',
include: [
path.resolve(__dirname, 'Source')
],
},
{
test: /\.worker\.ts$/,
loader: 'worker-loader',
options: {
esModule: false,
}
},
{
test: /\.(svg|png|jpg|gif|ico)$/i,
use: {
loader: 'file-loader',
options: {
name: '[name].[hash].[ext]',
outputPath: "Images"
}
}
},
{
test: /\.html$/,
use: ['html-loader']
}
]
}
};
webpack.dev.config
const path = require('path');
const common = require('./webpack.config');
const merge = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const {CleanWebpackPlugin} = require("clean-webpack-plugin");
module.exports = merge.merge(common, {
mode: 'development',
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'Build')
},
plugins: [
new MiniCssExtractPlugin(
{
filename: '[name].[contenthash].css'
}
),
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'Source', 'template.html'),
filename: 'Index.html'
})
],
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
},
{
enforce: "pre",
test: "/\.js$/",
loader: "source-map-loader"
}
]
},
devtool: 'source-map'
});
Once this is build my Output Folder looks like this:
1a901b56586b6444ae11.ico <-- these should no be here have 0 byte
c4f9748e8b8d4038f05c.png <-- these should no be here have 0 byte
Index.html
main.90957f37ae16dde06736.js
main.90957f37ae16dde06736.js.map
main.cf18790244b83b75a490.css
main.cf18790244b83b75a490.css.map
vendor.1ce4fff9da8447255aaf.js
Images\Favicon.fba6e1cd14b7ac368970b6418b5c67ac.ico
Images\Logo.86047b7e6019c39da248c24c90924f8c.png
The references in the htmls change like this
template.html
<link rel="icon" href="Images/Favicon.ico">
...
<img src="./Images/Logo.png">
Index.html
<link rel="icon" href="1a901b56586b6444ae11.ico">
...
<img src="c4f9748e8b8d4038f05c.png">
I've tested this with the a template I found here were it worked:
https://github.com/Colt/webpack-demo-app
I am currently switching a web app to have its assets bundled using Webpack. Bundling JS and CSS was somewhat straightforward. Then came the turn of images. My question is how one can approach bundling images.
In particular, suppose I have static_src from which everything originates and static_compiled into which the bundled output is placed. I would like the image contents of static_src/img to move into static_compiled/img. How does one accomplish this?
On another note, is this a sensible approach or am I misunderstanding some philosophy behind Webpack and misusing it?
Current config is roughly like this:
var webpack = require('webpack')
var BundleTracker = require('webpack-bundle-tracker')
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
entry: { index: path.resolve(__dirname, "static_src", "index.js") },
output: {
path: path.resolve(__dirname, "static_compiled"),
publicPath: "/static/", // Should match Django STATIC_URL
filename: "[name].js", // No filename hashing, Django takes care of this
chunkFilename: "[id]-[chunkhash].js", // DO have Webpack hash chunk filename, see below
},
plugins: [
new BundleTracker({filename: './webpack-stats.json'}),
],
module: {
rules: [
{
test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel-loader'}, // to transform JSX into JS
{
test: /\.scss$/, use: ["style-loader", "css-loader", "sass-loader"]},
{
test: /\.css$/, use: ["style-loader", "css-loader"]},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
loader: 'file-loader'},
{
test: /\.svg$/,
loader: 'svg-inline-loader'},
/* {
test: /\.(ico|png|jpg|gif)$/,
loader: 'file-loader'} */
{
test: /\.(ico|png|svg|jpg|gif|jpe?g)$/,
use: [
{
options: {
name: "[name].[ext]",
outputPath: "img/"
},
loader: "file-loader"
}
]
}
],
},
resolve: {
alias: {
shared: path.resolve(__dirname, 'node_modules', 'bower_components')
},
extensions: ['.js', '.ts', 'jsx', 'tsx']
},
devServer: {
writeToDisk: true, // Write files to disk in dev mode, so Django can serve the assets
}
}
The code I ended up using looks something like this.
plugins section:
plugins: [...
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, `static_src/img`),
to: 'img',
}
]
}),
module-rules section:
module: {
rules: [
{ ...
test: /\.(ico|png|jpg|gif|jpe?g)$/,
use: [
{
loader: "file-loader",
options: {
name: "[name].[ext]",
outputPath: "img/"
}
}
]
}
I just installed react, webpack, and babel into one of my projects (I used this tutorial https://medium.com/swlh/a-complete-webpack-setup-for-react-e56a2edf78ae but I tweaked a bit of the webpack.config.js file because it was giving errors) and now my css stylesheet for my html file doesn't link (when I type npm run start) and I'm not exactly sure why
This is how I link my stylesheet
<link rel="stylesheet" type="text/css" media="screen" href="index-styles.css">
This is my webpack.config.js
const path = require("path");
const autoprefixer = require("autoprefixer");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js",
chunkFilename: "[id].js",
publicPath: ""
},
resolve: {
extensions: [".js", ".jsx"]
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{ loader: "style-loader" },
{
loader: "css-loader",
options: {
modules: {
localIdentName: "[name]__[local]___[hash:base64:5]"
},
sourceMap: true
}
},
{
loader: "postcss-loader"
// postcssOptions: {
// ident: "postcss",
// options: {
// }
// //plugins: () => [autoprefixer({})]
// }
}
]
},
{
test: /\.(png|jpe?g|gif)$/,
loader: "url-loader?limit=10000&name=img/[name].[ext]"
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: __dirname + "/src/index.html",
filename: "index.html",
inject: "body"
})
]
};
And right now my project structure is
assets
images
node_modules
src
|___index-styles.css (one I'm linking to index.html)
|___index.css (one used in index.js for tutorial)
|___index.html
|___index.js
.babelrc
package-lock.json
package.json
webpack.config.js
For some reason my webpack configuration is loading the images that comes from my SCSS files but not the ones that come from the HTML files. Also when I run the BUILD command in order to deliver my prod archives it does not create the "img" folder. To be honest I'm pretty new with webpack 4 and I guess there's a couple of steps that I'm not including on the WP config file.
This is my webpack.dev.js
This is the prod folder structure that I would want to create:
dist
|----img
|----css
|----js
a.html
b.html
c.html
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
module.exports = {
entry: {
main: "./src/js/scripts.js"
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/[name].[hash].js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.scss$/,
use: [
"style-loader",
MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
"sass-loader"
]
},
{
test: /\.(png|jpg|gif)$/,
use: ["url-loader"]
}
]
},
devServer: {
port: 8080
},
plugins: [
new CleanWebpackPlugin("dist", {}),
new MiniCssExtractPlugin({
filename: "css/style.[contenthash].css"
}),
new HtmlWebpackPlugin({
template: "./src/index.html",
inject: false,
hash: true,
filename: "index.html"
}),
new HtmlWebpackPlugin({
template: "./src/actualitat.html",
inject: false,
hash: true,
filename: "actualitat.html"
}),
new HtmlWebpackPlugin({
template: "./src/projectes.html",
inject: false,
hash: true,
filename: "projectes.html"
})
]
};
This is the way im loading both css and js on my html files:
<link
rel="stylesheet"
href="<%=htmlWebpackPlugin.files.chunks.main.css %>"
/>
<script src="<%= htmlWebpackPlugin.files.chunks.main.entry %>"></script>
I have a "scripts.js" js file where I import the files like this:
import "../scss/style.scss";
import "../img/searchBar-icon.png";
import "../img/townHall.png";
import "../img/icon-title.png";
UPDATE:
I have change the way im loading images using the "file-loader" loader:
{
test: /\.(png|jpg|gif)$/,
use: {
loader: "file-loader",
options: {
outputPath: "img/",
name: "[name][hash].[ext]"
}
}
}
Now all of my images are being copied to the "img" folder which is good, problem is that all the names of the files have hashes now (which make sense since I'm telling the loader to add them) and they're not loading on my html files.
Can you try the following for loading the images?
{
test: /\.(jpe?g|png|gif|ico)$/i,
use: ["file-loader?name=[name].[hash].[ext]"]
}
i want to separate my project file to multi files.
with sass and JavaScript import, i can do that just for styles and scripts.
but i want to separate HTML files too.
i dont use any frameworks just webpack.
according to webpack documentation, we can do that with interpolation
https://webpack.js.org/loaders/html-loader/#interpolation
require("html-loader?interpolate!./file.html");
<div>${require('./components/gallery.html')}</div>
but i got error:
Cannot find module 'html-loader?interpolate!./file.html'
my webpack config:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const webpack = require('webpack');
require("html-loader?interpolate!./file.html");
module.exports = {
devtool: 'source-map', // to see source map of scss and ts
entry: [ // root files to load
'./node_modules/material-design-lite/material.min.js',
'./src/scripts/main.ts',
'./src/index.html',
'./src/styles/main.scss',
],
mode: 'development',
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
loader: 'ts-loader',
options: {
transpileOnly: false
}
},
{ // to auto refresh index.html and other html
test: /\.html$/,
loader: "raw-loader",
exclude: /node_modules/,
},
{
test: /\.html$/,
use: [ {
loader: 'html-loader',
}],
},
{
test: /\.scss$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader", options: {
sourceMap: true
}
}, {
loader: "sass-loader", options: {
sourceMap: true
}
}]
},
{ // for images and fonts in scss file
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
use: [{
loader: 'url-loader',
options: {
limit: 8000, // Convert images < 8kb to base64 strings
name: 'images/[hash]-[name].[ext]'
}
}]
}
]
},
resolve: {
extensions: ['.ts', '.js', '.json'],
plugins: [
// to get access of custom typescript paths. (e.g. _app/XXX/XX or #app/XXX/XX)
new TsconfigPathsPlugin({ configFile: __dirname + "/tsconfig.json" })
]
},
output: {
filename: "./bundle.js",
path: path.resolve(__dirname, './build'),
},
plugins: [
// use for html pre complier like jade
// new HtmlWebpackPlugin({
// filename: 'index.html',
// path: path.resolve(__dirname, './build'),
// template: './src/index.jade',
// inject: 'body',
// }),
new HtmlWebpackPlugin({
template: './src/index.html'
}),
// copy assets folder to access file from html or as http request
new CopyWebpackPlugin([{
from: './src/assets',
to: path.resolve(__dirname, './build/assets')
}]),
// to use hot, inline (auto refresh) in config file. with out this we have to set as command of webpack-dev-server
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: path.resolve(__dirname, './build'),
hot: true, // for auto refresh
inline: true, // for auto refresh
port: 3000,
overlay: true // for show error on html
}
}
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Zoom.FM</title>
</head>
<body>
<div class="side-nav mdl-list">
<div>${require('./myfile.html')}</div>
</body>
</html>
how can i do that or how interpolation work?
I found answer :)
remove require("html-loader?interpolate!./file.html")
enable interpolate in webpack config
webpack config
{
test: /\.html$/,
use: [ {
loader: 'html-loader',
options: {
interpolate: true
}
}],
},