Just confused with my webpack and less set up best way to include urls for images in my css and have them working in dev and build mode.
Following worked in dev using webpack-devserver but not after build.
.login-container{
height:100%;
width:100%;
background: url('../../images/home3.jpg') no-repeat center center fixed;
And in my config.
plugins.push(
new HtmlWebpackPlugin({
template: './src/index.html',
inject: 'body'
}),
// Write out CSS bundle to its own file:
new ExtractTextPlugin({
filename: 'css/styles.css',
allChunks: true})
);
Also
entry: {
app: './src/app/app.js'
},
devServer: {
outputPath: path.join(__dirname, 'src'),
contentBase: "./src"
},
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: isProd ? '' : 'http://localhost:8080/',
filename: isProd ? 'js/[name].[hash].js' : 'js/[name].bundle.js',
chunkFilename: isProd ? 'js/[name].[hash].js' : 'js/[name].bundle.js'
},
In dev it worked fine but after build it was trying to load the images from my css folder
i.e. mysites/css/12424324234234234.jpg
instead of
i.e. mysites/12424324234234234.jpg where the images really was.
Here these solutions posted in the following Github issues might help you.
Github Issues 1
Github Issues 2
The workaround for the process can be done as this
The ExtractTextPlugin need to handle a filename like css/[name].css. As workaround you could use [name].css instead.
set { publicPath: '/' } so that each reference becomes root relative.
OR
you can also use url-loader
You can also check this committed posted by sokra
code loaders: [
{ test: /\.css$/, loader: ExtractTextPlugin.extract(
"style-loader",
"css-loader?sourceMap"
"css-loader?sourceMap",
{
publicPath: "../"
}
)},
{ test: /\.png$/, loader: "file-loader" }
]
},
plugins: [
new ExtractTextPlugin("[name].css?[hash]-[chunkhash]-[name]", {
new ExtractTextPlugin("css/[name].css?[hash]-[chunkhash]-[name]", {
disable: false,
allChunks: true
}),
Related
Im a new beginner on develop react app.
Im trying to figure out how to set up my webpack.config.js file.
I have following ended up with this structure as you can see on the picture link below.
My question is: When im running 'npm run build' , its hashing the picture and put it into the /dist folder. How can i configure so it does not?
Because im using copyWebpackPlugin() to copy my images and push it to the dist folder, but i dont want the picture which i marked with arrow.
If anyone have some advice just bring it on.
This is how my webpack.config.js file look like:
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
entry: "./src/index.js",
mode: "development",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader"
},
{
test: /\.s?css$/,
loader: ["style-loader", "css-loader"]
},
{
test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg)(\?[a-z0-9=.]+)?$/,
loader: "url-loader?limit=100000"
}
]
},
resolve: { extensions: [".js", ".jsx"] },
output: {
path: path.resolve(__dirname, "dist/"),
filename: "bundle.js"
},
devtool: "cheap-module-eval-source-map",
devServer: {
contentBase: path.join(__dirname, "public/"),
proxy: {
"/api/*": {
target: "http://localhost:3000/",
secure: "true"
}
},
port: 4000,
publicPath: "http://localhost:4000/dist/",
hotOnly: true,
historyApiFallback: true
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new CleanWebpackPlugin(["dist"]),
new HtmlWebpackPlugin({
filename: "index.html",
template: "./public/index.html"
}),
new CopyWebpackPlugin([{ from: "public/images", to: "images" }])
]
};
I would suggest instead of copy-webpack-plugin use file-loader to copy images
{
test: /\.(png|jpg|gif|jpeg)$/,
use: [{
loader: 'file-loader',
options: {
name: 'images/[name].[ext]',
}
}]
}
if you want hash instead of name
name: 'images/[hash].[ext]',
Package
npm install --save-dev file-loader
It is because the url-loader has a default fallback to file-loader. So if your image is bigger than the limit you have set for url-loader, it does not rewrite the image to base64 data:image in your css, instead gives it to file-loader and it copies that image to your dist folder (output path).
So if you do not want this, disable the fallback option for url-loader
But I also think you should have configure your webpack to copy the files with file-loader properly instead that copy plugin. But you know...
I would give you an example based on your config but I am currently on mobile so I can't code right now.
I'm running this command to try & generate a production webpack build:
rimraf ./build/* && webpack -p --progress --config webpack.production.js
However, when I open up the build/index.html, it's failing to load a lot of files because the locations are off.
It fails to put the correct location for the bundle.js file. It loads it like this: /bundle.js. However the bundle.js file is actually in the same directory as the index.html file in the build folder so it should load it like this ./bundle.js
If I correct the bundle.js path, it's still putting an incorrect route for the assets:
What's interesting is that my app currently works with the webpack dev server when I run: webpack-dev-server --inline --progress --config webpack.dev.js.
Here is what my current webpack.production.js file looks like:
var webpack = require('webpack');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'source-map',
devServer: {
historyApiFallback: true, // This will make the server understand "/some-link" routs instead of "/#/some-link"
},
entry: [
'./src/scripts' // This is where Webpack will be looking for the entry index.js file
],
output: {
path: path.join(__dirname, 'build'), // This is used to specify folder for producion bundle
filename: 'bundle.js', // Filename for production bundle
publicPath: '/'
},
resolve: {
modules: [
'node_modules',
'src',
path.resolve(__dirname, 'src/scripts'),
path.resolve(__dirname, 'node_modules')
], // Folders where Webpack is going to look for files to bundle together
extensions: ['.jsx', '.js'] // Extensions that Webpack is going to expect
},
module: {
// Loaders allow you to preprocess files as you require() or “load” them.
// Loaders are kind of like “tasks” in other build tools, and provide a powerful way to handle frontend build steps.
loaders: [
{
test: /\.jsx?$/, // Here we're going to use JS for react components but including JSX in case this extension is preferable
include: [
path.resolve(__dirname, "src"),
],
loader: ['react-hot-loader']
},
{
loader: "babel-loader",
// Skip any files outside of your project's `src` directory
include: [
path.resolve(__dirname, "src"),
],
// Only run `.js` and `.jsx` files through Babel
test: /\.jsx?$/,
// Options to configure babel with
query: {
plugins: ['transform-runtime'],
presets: ['es2015', 'stage-0', 'react'],
}
},
{
test: /\.scss$/,
loaders: ['style-loader', 'css-loader', 'sass-loader']
}
]
},
plugins: [
new webpack.NoEmitOnErrorsPlugin(), // Webpack will let you know if there are any errors
// Declare global variables
new webpack.ProvidePlugin({
React: 'react',
ReactDOM: 'react-dom',
_: 'lodash'
}),
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/index.html',
hash: true
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true
}),
]
}
And just in case, this is what my current webpack.dev.js file looks like:
var webpack = require('webpack');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'cheap-module-source-map',
devServer: {
historyApiFallback: true, // This will make the server understand "/some-link" routs instead of "/#/some-link"
},
entry: [
'babel-polyfill',
'webpack-dev-server/client?http://127.0.0.1:8080/', // Specify the local server port
'webpack/hot/only-dev-server', // Enable hot reloading
'./src/scripts' // This is where Webpack will be looking for the entry index.js file
],
output: {
path: path.join(__dirname, 'build'), // This is used to specify folder for producion bundle
filename: 'bundle.js', // Filename for production bundle
publicPath: '/'
},
resolve: {
modules: [
'node_modules',
'src',
path.resolve(__dirname, 'src/scripts'),
path.resolve(__dirname, 'node_modules')
], // Folders where Webpack is going to look for files to bundle together
extensions: ['.jsx', '.js'] // Extensions that Webpack is going to expect
},
module: {
// Loaders allow you to preprocess files as you require() or “load” them.
// Loaders are kind of like “tasks” in other build tools, and provide a powerful way to handle frontend build steps.
loaders: [
{
test: /\.jsx?$/, // Here we're going to use JS for react components but including JSX in case this extension is preferable
include: [
path.resolve(__dirname, "src"),
],
loader: ['react-hot-loader']
},
{
loader: "babel-loader",
// Skip any files outside of your project's `src` directory
include: [
path.resolve(__dirname, "src"),
],
// Only run `.js` and `.jsx` files through Babel
test: /\.jsx?$/,
// Options to configure babel with
query: {
plugins: ['transform-runtime', 'transform-decorators-legacy'],
presets: ['es2015', 'stage-0', 'react'],
}
},
{
test: /\.scss$/,
loaders: ['style-loader', 'css-loader', 'sass-loader']
}
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(), // Hot reloading
new webpack.NoEmitOnErrorsPlugin(), // Webpack will let you know if there are any errors
// Declare global variables
new webpack.ProvidePlugin({
React: 'react',
ReactDOM: 'react-dom',
_: 'lodash'
}),
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/index.html',
hash: false
})
]
}
Any ideas what I'm doing wrong?
faced a similar issue. setting output.publicPath: "/" in webpack.dev.js and output.publicPath: "./" in webpack.prod.js, did the trick for me.
Got the same error when running npm run watch, local dev still worked, but after deploying to demo server the app crashed on wrong js-file url.
Cause:
Some changes in my webpack.mix.js started compiling a index.html file that was found by the browser, instead of the app.blade I was using.
Fixed the paths by setting: publicPath: './public/'
(Note that it's a relative path). Also, I removed the generated url by setting inject: false, in the HtmlWebpackPlugin({ section and used the asset('/...') logic.
I am recently learning React and have problem setting webpack. I wrote a background image in sass file but I can't see this image in browser, I checked the develope tool and saw a strange file name as the attatched picture shows. There's no error when I run webpack. I think I might set the webpack.config.js incorrectly. Can somebody take a look for me? here's the source code:
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: [
'eventsource-polyfill',
'./src/index'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/'
},
module: {
loaders: [
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
},
{
test: /\.sass$/,
loader: 'style!css?sourceMap!sass'
},
{
test: /\.(jpg|gif|png)$/,
loader: "file"
},
{
test: /\.(jpg|gif|png)$/,
loader: "url"
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src', 'index.html'),
filename: 'index.html',
inject: 'body',
})
]
};
I also put my files on github: https://github.com/john650914/ReactQuestion.git
Thank you very much~~~~~~~~~
Webpack will start looking for your url path at '/' which was set by your publicPath in your webpack.config.js
Looking at your repository with your link provided:
https://github.com/john650914/ReactQuestion.git
It seems like your image isn't in your projects root. You should specify the correct publicPath that leads to where you store your assets. So for example if you stored your images in /src/assets/ then your publicPath should be ./src/assets/ like this:
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: './src/assets/'
},
I have images path in css like url(images/image1.jpg) and the loader is defined as
{ test: /\.(png|woff|woff2|eot|ttf|svg|jpg)$/, loader: 'url-loader?limit=1&name=images/[name].[ext]' },
The issue I am facing is that after build process the images are copied to respective folder but the path is pointing to images/image1.jpg relative to the css file location. I want it to be relative to the root directory.
I tried adding a leading / in the name query parameter and it partially fixed the issue
{ test: /\.(png|woff|woff2|eot|ttf|svg|jpg)$/, loader: 'url-loader?limit=1&name=images/[name].[ext]' },
but when I move my files into a sub folder it still points to the root of the domain instead of the folder.
Can you tell me what I am missing in the configuration?
Here is the webpack configuration
'use strict';
var webpack = require('webpack'),
HtmlWebpackPlugin = require('html-webpack-plugin'),
OpenBrowserPlugin = require('open-browser-webpack-plugin'),
ExtractTextPlugin = require('extract-text-webpack-plugin'),
path = require('path'),
srcPath = path.join(__dirname, 'src'),
jsDestPath = 'scripts/';
module.exports = {
target: 'web',
cache: true,
entry: {
common: ['react', 'react-router', 'alt', 'es6-promise'],
offline: path.join(srcPath, 'libs/offline.min.js'),
materialize: path.join(srcPath, 'libs/materialize.js'),
css3_animate_it: path.join(srcPath, 'libs/css3-animate-it.js'),
app: path.join(srcPath, 'App.js')
},
resolve: {
root: srcPath,
extensions: ['', '.js'],
modulesDirectories: ['node_modules']
},
output: {
path: path.join(__dirname, 'build'),
publicPath: '',
filename: jsDestPath + '[name].js',
library: ['Example', '[name]'],
pathInfo: true
},
module: {
loaders: [
{
test: /\.js?$/,
exclude: /node_modules/,
loader: 'babel?cacheDirectory'
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader")
},
/*{
test: /\.(png|woff|woff2|eot|ttf|svg|jpg)$/,
loader: 'url-loader?limit=5' // inline base64 URLs for <=8k images, direct URLs for the rest
},*/
{ test: /\.(png|woff|woff2|eot|ttf|svg|jpg)$/, loader: 'url-loader?limit=1&name=images/[name].[ext]' },
{
test: /\.rt/,
loader: "react-templates-loader"
}
],
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery"
}),
new webpack.optimize.CommonsChunkPlugin('common', jsDestPath + 'common.js'),
new webpack.optimize.UglifyJsPlugin({minimize: true}),
new HtmlWebpackPlugin({
inject: true,
template: 'src/index.html'
}),
new OpenBrowserPlugin({
url: 'http://localhost:8080',
browser: 'Chrome'
}),
new webpack.NoErrorsPlugin(),
new ExtractTextPlugin("styles/style.css", {
allChunks: true
})
],
debug: true,
//devtool: 'eval-source-map',//'eval-cheap-module-source-map',
devServer: {
contentBase: './build',
historyApiFallback: true
}
};
Remove publicPath: '', or set it to publicPath: '/', and require images
like this let imgSrc = require('../../img/image.png'); via relative paths(from where you are trying to require images).
It should get resolved as {publicPath}/images/[name].[ext]
I hope it should work.
You need to prefix your image URL with ~, otherwise it will be treated as relative to the CSS path. The ~ triggers webpack's normal module resolution. More info in the CSS loader docs here.
I am facing this strange issue with Webpack. After spending hours couldn't find solution.
In my jsx file when I a try to set image source via this
let img = require('../../../img/imgN.png');
It is working perfectly but when I try to set the background image using scss via
$bg-img: url('../img/bg-img.png');
Image is not getting loading by webpack.
This is my webpack file
module.exports = {
devtool: 'source-map',
entry: {
main: [
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'./src/index.js'
]
},
output: {
path: path.join(__dirname, 'public'),
publicPath: '/public/',
filename: 'bundle.js'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
module: {
loaders: [
{
test: /\.jsx?$/,
include: path.join(__dirname, 'src'),
loader: 'react-hot!babel'
},
{
test: /\.scss$/,
include: path.join(__dirname, 'sass'),
loaders: ["style", "css?sourceMap", "sass?sourceMap"]
},
{
test: /\.(png|jpg)$/,
include: path.join(__dirname, 'img'),
loader: 'url-loader?limit=30000'
} // inline base64 URLs for <=30k images, direct URLs for the rest
]
},
resolve: {
extensions: ['', '.js', '.jsx']
},
devServer: {
historyApiFallback: true,
contentBase: './'
}
}
Problem was occurring because of using sourceMap with style-loader.
There is some issue on github for the same problem.
Solution:
1 . While source-maps is enabled
Style-loader uses a Blob, so it requires absolute urls to work.
Changed publicPath: '/public/', to
publicPath: 'http://localhost:8080/public/',
It worked.
Without source-maps
Just remove source map from style loaders.
Now style-loader will use an inline style tag, so there is no problem.
{
test: /\.scss$/,
include: path.join(__dirname, 'sass'),
loaders: ["style", "css", "sass"]
},
Can you try to see if $bg-img: url('~/img/bg-img.png'); would work? When I was trying out webpack in my bootstrap.scss files I had to modify the font url's using ~ (I think I read it somewhere but ya just giving you something to try)