I am using webpack with reactJs.
I am trying, with css, to set background-image.
when I build my project I always get the same path for img url no matter what I try.
'http://localhost:8080/images/img1.png '
instead of - 'http://localhost:8080/dist/images/img1.png'
Folder structure:
src/
App/
app.jsx
app.html
app.css
public/
images/
img1.png
img2.png
index.jsx
index.html
dist/
images/
img1.png
img2.png
bundle.js
main.bundle.css
index.html
webpack.config.js
webpack.config.js
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
// HTML plugin options
let htmlOptions = {
template: './src/index.html',
filename: 'index.html',
inject: 'body',
}
module.exports = {
entry: './src/index.jsx',
output: {
path: path.resolve('dist'),
filename: 'bundle.js',
},
resolve: {
extensions: ['.js', '.jsx', '.css']
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-3']
},
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.jpe?g$|\.ico$|\.gif$|\.png$|\.svg$|\.wav$|\.mp3$/,
loader: 'file-loader',
options: {
outputPath: 'img/',
name: '[name].[ext]',
publicPath: '/dist'
}
},
{
test: /\.(ttf|eot|woff|woff2)$/,
use: {
loader: "file-loader",
options: {
name: "fonts/[name].[ext]",
},
},
},
]
},
devtool: 'source-map',
plugins: [
new HtmlWebpackPlugin(htmlOptions),
new CleanWebpackPlugin(['dist']),
new CopyWebpackPlugin([{ from: __dirname + '/src/public' }])
],
devServer: {
historyApiFallback: true
}
}
app.css
body{
background-image: url('/images/loginImageBg.png');
}
**I have tried **
plugins : new ExtractTextPlugin - for some resone Conflicts with cleanWebpackPlugin.
url-loader
query: {outputPath: './data/'}
publicPath , outputPath
nothing I do seems to work
Please help !
Related
When I use a relative url in an SCSS file (I am trying to set the background-image property to a local file), I receive the following error:
Any idea how what is going wrong?
I have a project with the following structure:
public/
dist/
images/
wave.png
index.html
src/
components/
MyComponent.js
app.js
styles/
base/
components/
_my-component.scss
styles.scss
webpack.config.js
In MyComponent.js I render <div className="bg"></div>.
In _my-component.scss I have:
.bg {
background-image: url("/images/wave.png");
}
And in webpack.config.js I have:
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.join(__dirname, "public", "dist"),
filename: "bundle.js"
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/
},
{
test: /\.s?css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
sourceMap: true
}
},
{
loader: "sass-loader",
options: {
sourceMap: true
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "styles.css"
})
],
devtool: isProduction ? "source-map" : "inline-source-map",
devServer: {
contentBase: path.join(__dirname, "public"),
historyApiFallback: true,
publicPath: "/dist/"
}
};
};
In _my-component.scss, directories are only relative to this file. According to your directory tree, you would need to go up 2 directories, which is essentially back to the root/home directory, and then one directory down to the public folder.
Try this path in your script: ../../public/images/wave.png
Using a Webpack and PostCSS environment I would like to import all CSS files in my Components folder and the subdirectory. I've tried both PostCSS plugins postcss-easy-import & postcss-import and know they both need to come first. Regular Imports with direct paths work, could it be that ** placeholders don't work?
Thanks in advance
The best practice to import css or scss files is importing all your css files or components in one main.css or scss file. Then import that file in your entry *.js file and finally set that *.js file in your webpack config file as an entry.
For example if you have a folder called SampleProject and a folder and file structure like this:
SampleProject
|
|--css
| |--components
| | |--style1.css
| | |--style2.css
| | |--style3.css
|
|--js
| |--components
| | |--script1.js
| | |--script2.js
|
main.css
index.js
index.html
webpack.prod.js
package.json
Then you can import all you 3 style files in your main.css file like below:
main.css
#import 'css/components/style1.css';
#import 'css/components/style2.css';
#import 'css/components/style3.css';
Then you can import the main.css file into index.js with other js chunks like this:
index.js
import './main.css';
import 'js/components/script1.js';
import 'js/components/script2.js';
Finally, you can use this index.js as an entry point into your webpack config file like this:
webpack.prod.js:
const webpack = require('webpack');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = {
entry: {
main: './index.js'
},
output: {
path: path.join(__dirname, './build'),
filename: '[name].[chunkhash:8].bundle.js',
chunkFilename: '[name].[chunkhash:8].chunk.js',
},
mode: 'production',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
//'sass-loader',
],
},
{
test: /\.(png|svg|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/img',
esModule: false,
},
},
],
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/font',
},
},
],
},
{
test: /\.html$/i,
use: {
loader: 'html-loader',
options: {
attributes: {
list: [
{
tag: 'img',
attribute: 'src',
type: 'src',
},
{
tag: 'img',
attribute: 'srcset',
type: 'srcset',
},
{
tag: 'img',
attribute: 'data-src',
type: 'src',
},
{
tag: 'img',
attribute: 'data-srcset',
type: 'srcset',
},
],
},
},
},
},
],
},
optimization: {
minimizer: [new TerserJSPlugin(), new OptimizeCSSAssetsPlugin()],
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
chunks: 'all',
},
runtimeChunk: {
name: 'runtime',
},
},
plugins: [
// load jQuery
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
}),
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: '[name].[chunkhash:8].bundle.css',
chunkFilename: '[name].[chunkhash:8].chunk.css',
}),
new HtmlWebpackPlugin({
chunks: ['main'],
template: 'index.html',
filename: 'index.html',
}),
],
};
And MiniCssExtractPlugin will extract all styles of your project automatically and save them as one file in build folder in root of your project.
When I run npm run build "build": "webpack" webpack produces dist folder for me with main.css, index.html and index.js but the images from CSS or from HTML don't work and they are not there.
In CSS in dist folder they are referenced like so
background-image: url("../../../assets/img/works/works-3.jpg");
And in HTML
<img src="./assets/img/logo.png">
I'm not sure what to fix so my images are working.
I have this webpack config
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const SpritesmithPlugin = require('webpack-spritesmith');
var path = require('path');
module.exports = {
mode: 'development',
entry: './src/app.js',
module: {
rules: [
{
test: /\.css$|\.sass$|\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader?url=false'
},
{ loader: 'sass-loader' }
]
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{test: /\.png$|jpg|jpeg/, use: [
'file-loader?name=i/[hash].[ext]'
]}
]
},
resolve: {
extensions: ['.js', '.es6'],
modules: ['node_modules', 'spritesmith-generated']
},
output: {
path: __dirname + '/dist',
filename: 'index.js'
},
devServer: {
port: 8080,
contentBase: './src',
watchContentBase: true
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css'
}),
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new SpritesmithPlugin({
src: {
cwd: path.resolve(__dirname, 'src/assets/img/icons'),
glob: '*.png'
},
target: {
image: path.resolve(__dirname, 'src/spritesmith-generated/sprite.png'),
css: path.resolve(__dirname, 'src/spritesmith-generated/sprite.scss')
},
apiOptions: {
cssImageRef: '../spritesmith-generated/sprite.png'
}
})
]
};
UPD installed Copy Webpack Plugin and copied assets folder to dist folder. Images in HTML are working fine, but images in CSS do not.
After using CopyWebpackPlugin you need to need to change your background-url to /dist/images/imageName . But it depends how are structuring your build folder. This plugin copy all assets to your build folder so you need to import them from your dist folder.
When I bundling CSS from packages in node_modules, I get trouble with relativity of paths.
In original stylesheets images are requested from child folder. After bundling through Webpack folder names are right, but there is no ../ before path to image.
Attaching all, what I can provide, including project folder structure and webpack's config.
vendor.scss
#import "~leaflet/dist/leaflet.css";
#import "~leaflet-draw/dist/leaflet.draw.css";
#import "~leaflet-easybutton/src/easy-button.css";
Image imports in original leaflet.draw (css and html are in one folder)
url('images/[filename].[ext]')
Image imports after bundling (css is in child folder)
url('img/[filename].[ext]')
Folders structure
node_modules/
- leaflet-draw/
- - dist/
- - - leaflet-draw.css
- - - images/
- - - - [images]
src/
- scss/
- - vendor.scss
- index.html
dist/
- css/
- - vendor.css
- img/
- - [images from imported css]
- index.html
webpack.cofing.js
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
mode: 'development',
entry: {
'vendor': [
'./src/js/vendor.js',
'./src/scss/vendor.scss'
],
'fa': './src/js/fa.js',
'sanAndreas': [
'./src/js/sa.js',
'./src/scss/sa.scss'
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].js',
sourceMapFilename: '[file].map'
},
module: {
rules: [{
test: /\.js$/,
include: path.resolve(__dirname, 'src/js'),
use: {
loader: 'babel-loader',
options: {
presets: 'env'
}
}
},
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {name: 'img/[name].[ext]'}
},
]
},
{
test: /\.(sass|scss)$/,
include: path.resolve(__dirname, 'src/scss'),
use: ExtractTextPlugin.extract({
use: [{
loader: "css-loader",
options: {
sourceMap: true,
minimize: true
}
},
{
loader: 'resolve-url-loader'
},
{
loader: "sass-loader",
options: {
sourceMap: true
}
},
]
})
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
},
]
},
devtool: "source-map",
plugins: [
new CleanWebpackPlugin(['dist']),
new ExtractTextPlugin({
filename: './css/[name].css',
allChunks: true
}),
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html",
inject: false
}),
new HtmlWebPackPlugin({
template: "./src/sa.html",
filename: "./sa.html",
chunks: ['vendor', 'sanAndreas', 'fa']
}),
new HtmlWebPackPlugin({
template: "./src/five.html",
filename: "./five.html",
chunks: []
})
]
}
I have configured my webpack.config.js as following:
var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
var path = require('path');
// plugins
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
context: path.join(__dirname, "src"),
devtool: debug ? "inline-sourcemap" : null,
entry: "./js/init.js",
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel',
query: {
presets: ['react', 'es2015', 'stage-0'],
plugins: ['react-html-attrs', 'transform-decorators-legacy', 'transform-class-properties',],
}
},
{
test: /\.json$/,
include: /node_modules/,
loader: 'json-loader'
},
{
test: /\.scss$/,
loaders: ExtractTextPlugin.extract(
'style',
'css!sass'
)
}
]
},
output: {
path: __dirname + "/src/",
filename: "app.js"
},
plugins: debug ? [] : [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
new ExtractTextPlugin('default.css'),
],
devServer: {
port: 3000,
historyApiFallback: {
index: 'index.html'
}
},
sassLoader: {
includePaths: [path.resolve(__dirname, "src/css/sass")]
},
resolve: {
alias: {
'#': path.resolve(__dirname, 'src/js'),
'!': path.resolve(__dirname, 'src/css/sass')
}
},
};
And this is my file structure:
- src
-- css
--- sass
---- default.scss
-- js
-- index.html
Yet I don't see my default.css file exported anywhere when I run webpack dev server. Does it not work with webpack dev server?
Edit: Simply running webpack does not work either.