My project is not a JS web app. It is a traditional CMS with PHP templates that invoke the needed JS and CSS files. I'm using webpack4 with this goals:
For JS: Bundle, minify, polyfill, and create a js sourcemap --which is working well, no problem here.
Copy assests (fonts and images) from a folder in src. to another in dist. --working too.
For my SCSS files: compile Sass from a given directory, add prefixes, and output a single css file onto an specific folder, including the CSS SOURCEMAP.
Everything is working BUT I cannot generate the CSS sourcemap. I can do all this with Grunt, but I was hoping to only use one tool -webpack!
I'm pasting my config file to see if anyone spots what is wrong.
I already tried adding options:{ sourceMap:true,} to this loaders:
sass-loader, postcss-loader, css-loader
but then I get a long list of errors that seem to emanate from extrac-loader.
I appreciate any hints or help on this issue. I already spent 2 days troubleshooting it without any progress!
const path = require('path');
const OptimizeCSSAssetsPlugin = require(
"optimize-css-assets-webpack-plugin"
); // Recommended for Minifying outputted css
const cssnano = require("cssnano"); // Used by OptimizeCSSAssetsPlugin
var webpack = require('webpack'); // used by SourceMapDevToolPlugin --which was recommended over devtool.
module.exports = {
cache: false,
entry: {
'main': [ // forces webpack to process specified files
'../src/js/main.js',
'../src/sass/screen.scss',
],
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, '../dist/js'), // watchout: all output paths in 'rules' will be relative to this path
},
mode: 'development',
devtool: false, // passes sourcemap control to SourceMapDevToolPlugin
module:{
rules: [
{
test: /\.scss$/,
use: [
{
loader: 'file-loader',
options: {
name: '../css/[name].css', // Destination of final processed css file
}
},
{
loader: 'extract-loader', //The extract-loader evaluates the given source code on the fly and returns the result as string.
},
{
loader: 'css-loader?-url', //The css-loader interprets #import and url() like import/require() and will resolve them.
},
{
loader: 'postcss-loader', // adds prefixes
},
{
loader: 'sass-loader', // Loads a Sass/SCSS file and compiles it to CSS
},
]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets:
[
'#babel/env',
{
// "corejs": 3,
}
]
}
}
},
] // End of rules
}, // End of module
plugins: [
new webpack.SourceMapDevToolPlugin(
{
filename: '[name].map',
columns: false,
module: true,
}
),
new OptimizeCSSAssetsPlugin({
cssProcessor: cssnano,
cssProcessorOptions: {
discardComments: {
removeAll: true,
},
// Run cssnano in safe mode to avoid
// potentially unsafe transformations.
safe: true,
},
canPrint: false,
}),
],
} // End of module.exports
Ok, my approach was wrong. Modified a few things and now I have sourcemaps for js and css files.
I'm pasting my webpack.config file in case someone finds it useful (maybe this is obvious for most, but I'm new to webpack, hopefully this will help another newbie like me).
Changes I did:
I turns out that extract-loader and file-loader were not needed. I used mini-css-extract-plugin instead... which allows for the sourcemaps.
There's a conflict with optimize-css-assets-webpack-plugin (if you are using it for minification), so check the plugin part configuration to make sure your sitemaps are generted.
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // extracts and saves css files
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); // Minifies css
const cssnano = require("cssnano"); // Used by OptimizeCSSAssetsPlugin in the css minification
var webpack = require('webpack'); // used by SourceMapDevToolPlugin
module.exports = {
cache: false,
entry: {
'main': [ // forces webpack to process specified files
'../src/js/main.js',
'../src/sass/main.scss',
],
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, '../dist/js'), // watchout: all output paths in 'rules' will be relative to this path
},
mode: 'development',
devtool: false, // passes sourcemap control to SourceMapDevToolPlugin
module:{
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets:
[
'#babel/env',
{
// "corejs": 3,
}
]
}
}
},
{
test: /\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '/public/path/to/',
},
},
{
loader: 'css-loader', //The css-loader interprets #import and url() like import/require() and will resolve them.
options: {
url: false,
sourceMap: true,
},
},
{
loader: 'postcss-loader', // adds prefixes
options: {
sourceMap: true,
},
},
{
loader: 'sass-loader', // Loads a Sass/SCSS file and compiles it to CSS
options: {
sourceMap: true,
// importer: globImporter(),
},
},
]
},
] // End of rules
}, // End of module
plugins: [
new MiniCssExtractPlugin({
filename: '../css/[name].css'
}),
new OptimizeCSSAssetsPlugin({
cssProcessor: cssnano,
cssProcessorOptions: {
map: {
inline: false, // set to false if you want CSS source maps
annotation: true
},
discardComments: {
removeAll: true,
},
// Run cssnano in safe mode to avoid
// potentially unsafe transformations.
safe: true,
},
canPrint: false,
}),
new webpack.SourceMapDevToolPlugin(
{
filename: '[name].map',
columns: false,
module: true,
}
),
],
} // End of module.exports
Related
I am using file loader 6.2 to copy static image files into an images folder in my dist destination and it all works fine using the following config (ie the svg is copied from my src folder to the dist/images):
test: /\.(png|jpe?g|gif|svg)$/i,
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images',
publicPath: 'images',
},
However, as well as the static file being copied over, it also creates another file in the root of the dist folder that references the static - eg, when I copy a file called loading.svg, it creates that file as well as a file with a random hash (eg 817e56ed349aea52edfa.svg)
and inside this file, it just references the other file:
export default "images/loading.svg";
If I then check my compiled sass, I can see it references the hash file instead of the asset that was copied into the images folder.
background: url(../817e56ed349aea52edfa.svg) center center no-repeat;
How do I stop the extra file being created so that it only creates and references the image in the images folder directly?
On a side note, I tried swapping file loader for copy webpack plugin, and that also copied the files into the images folder, but on that occasion, instead of referencing that file, it just also created a hash version of the svg (but with the actual svg contents rather than a webpack export) in the root directory and referenced that instead - so it may be something else causing this issue? I include full webpack config below in case anyone can spot anything obvious or something else is causing the issue
Full webpack config
const paths = require("./webpack.paths");
const { VueLoaderPlugin } = require('vue-loader');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require("terser-webpack-plugin");
const isProduction = (process.env.NODE_ENV === 'production');
if (isProduction) {
console.log("Bundling in PRODUCTION mode")
} else {
console.log("Bundling in DEVELOPMENT mode")
}
module.exports = {
entry: {
styles: paths.styles,
home: './vue/templates/home/main.js',
},
mode: isProduction ? 'production' : 'development',
output: {
path: paths.dist,
filename: 'js/[name].js'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.(css|scss)$/,
use: [
MiniCssExtractPlugin.loader,
{
// Use the css-loader to parse and minify CSS imports.
loader: 'css-loader',
options: { sourceMap: true }
},
{
// Use the postcss-loader to add vendor prefixes via autoprefixer.
loader: 'postcss-loader',
options: {
postcssOptions: {
config: paths.postcssConfig,
},
sourceMap: true
}
},
{
// Use the sass-loader to parse and minify CSS imports.
loader: 'sass-loader',
options: { sourceMap: true }
},
],
},
{
test: /\.(png|jpe?g|gif|svg)$/i,
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images',
publicPath: 'images',
},
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['#babel/preset-env', { targets: "defaults" }],
]
}
},
},
]
},
devServer: {
hot: true,
noInfo: true,
overlay: true,
contentBase: [paths.root],
},
plugins: [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: 'css/[name].css'
}),
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: [
`${paths.dist}/css/*`,
`${paths.dist}/images/*`,
`${paths.dist}/js/*`,
],
}),
new ESLintPlugin({
extensions: ['vue', 'js'],
})
],
optimization: {
minimize: isProduction,
minimizer: [
new TerserPlugin(),
],
runtimeChunk: 'single',
splitChunks: {
minSize: 0,
cacheGroups: {
vendor: {
name: 'vendor',
chunks: 'all',
test: /[\\/]node_modules[\\/]/,
priority: 10,
enforce: true
}
}
}
}
}
if (isProduction) {
module.exports.plugins = (module.exports.plugins || []).concat([
new CompressionWebpackPlugin(),
])
}
In the end it looks as if it was the css loader that was causing the issue - so I configured it to ignore urls and then changed from the file-loader plugin to the copy-webpack-plugin to copy the images:
Ignore urls with css loader
MiniCssExtractPlugin.loader,
{
// Use the css-loader to parse and minify CSS imports.
loader: 'css-loader',
options: {
sourceMap: true,
url: false,
}
},
Copy webpack plugin to copy images
const CopyPlugin = require("copy-webpack-plugin");
plugins: [
new CopyPlugin({
patterns: [
{
from: 'vue/images', // src location
to: 'images', // destination location in dist folder
},
],
options: {
concurrency: 100,
},
}),
]
Then in my css I could just reference the image as relative from the dist folders css to the dist folder images folders:
background-image: url(../images/loading.svg);
Seems a bit odd to me that I had to do it this way in order not to get the extra svg file so if anyone comes up with a better solution or knows how not to create the extra file, please feel free to answer
I was creating react project and decided to escape create-react-app and create own custom template. So, then I wanted to dynamically add images via import like this
import picture1 from "../../assets/picture1.jpg";
import picture3 from "../../assets/picture3.jpg";
import picture5 from "../../assets/picture5.jpg";
So, to achieve that I installed file-loader and url-loader and set up the webpack config like this:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
// webpack will take the files from ./src/index
entry: "./src/index",
// and output it into /dist as bundle.js
output: {
path: path.join(__dirname, "/build"),
filename: "bundle.js",
},
// adding .ts and .tsx to resolve.extensions will help babel look for .ts and .tsx files to transpile
resolve: {
extensions: [".ts", ".tsx", ".js"],
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
enforce: "pre",
use: [
{
options: {
eslintPath: require.resolve("eslint"),
},
loader: require.resolve("eslint-loader"),
},
],
exclude: /node_modules/,
},
// we use babel-loader to load our jsx and tsx files
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: "url-loader",
options: {
limit: 8192,
},
},
],
},
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: "file-loader",
},
],
},
// css-loader to bundle all the css files into one file and style-loader to add all the styles inside the style tag of the document
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
],
};
So, pls let me know if I did everything right? Why don't I see the image when I run the project?
You should remove the file-loader and use the url-loader instead. Including the limit option will cause all files over 8192 bytes to use file-loader. So including the file loader rule is redundant. Furthermore anything under 8192 will be converted into a data url and included in the bundle.js.
I would do something like this:
module.exports = {
...
rules: {
{
test: /\.jpe?g$|\.gif$|\.png$/,
use: [
{
loader: 'url-loader',
options: {
mimetype: 'image/png',
limit: 8192
}
}
]
}
}
}
Been trying to research this but it doesn't seem as if any else has this, or see this as an issue.
I am using mini-css-extract-plugin(MiniCssExtractPlugin) in my webpack.config.js.
However, when I run webpack the console is littered with hundreds of instances of something similar to this...
Child mini-css-extract-plugin ../../../node_modules/css-loader/index.js??ref--6-1!../../../node_modules/postcss-loader/src/index.js!../../../node_modules/sass-loader/lib/loader.js!ui/radiolist-toggler/RadioListToggler.scss:
Entrypoint mini-css-extract-plugin = *
[../../../node_modules/css-loader/index.js?!../../../node_modules/postcss-loader/src/index.js!../../../node_modules/sass-loader/lib/loader.js!./ui/radiolist-toggler/RadioListToggler.scss] /Users/~~~/git/user-section/node_modules/css-loader??ref--6-1!/Users/~~~/git/user-section/node_modules/postcss-loader/src!/Users/~~/git/user-section/node_modules/sass-loader/lib/loader.js!./ui/radiolist-toggler/RadioListToggler.scss 5.33 KiB {mini-css-extract-plugin} [built]
+ 1 hidden module
I need to scroll up for a good few seconds to be able to see all my assets etc.
I am pretty new to webpack, so not exactly sure how to prevent this from being output to the console?
Below is my webpack.config.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const modernizr = require("modernizr");
const CopyWebpackPlugin = require('copy-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
context: path.resolve(__dirname, 'src/main/client'),
entry: './index',
devtool: 'cheap-module-source-map',
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
uglifyOptions: {
mangle: true,
compress: true,
ecma: 6
},
sourceMap: true
}),
new OptimizeCssAssetsPlugin({}),
],
splitChunks: {
chunks: 'all'
}
},
plugins: [
new CompressionPlugin({
test: /\.js$|\.css$|\.html$|\.(png|svg|jpg|gif)$/,
cache: true,
filename: '[path].gz[query]',
algorithm: 'gzip',
threshold: 10240
}),
new CleanWebpackPlugin([
'./target/webapp'
]),
new HtmlWebpackPlugin({
template: './index.html',
filename: '../index.html',
xhtml: true
}),
new MiniCssExtractPlugin({
filename: "[name].css",
}),
new CopyWebpackPlugin([{
from: '../webapp/**/*',
to: '../'
}]),
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"'
}),
],
output: {
publicPath: '/app/',
filename: '[name].bundle.js',
chunkFilename: '[id].js',
path: path.resolve(__dirname, 'target/webapp/app/')
},
module: {
rules: [{
loader: "webpack-modernizr-loader",
test: /\.modernizrrc\.js$/
},
{
test: /\.html$/,
exclude: /node_modules/,
use: {
loader: 'html-loader'
}
},
{
test: /\.s?css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 1
}
},
{
loader: 'postcss-loader'
},
{
loader: 'sass-loader'
}
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: './assets/fonts/'
}
}]
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: "babel-loader",
options: {
presets: ["#babel/env"]
}
}
],
},
resolve: {
alias: {
// You can add comment "Please do not delete this file" in this file
modernizr$: path.resolve(__dirname, "./.modernizrrc.js")
}
}
}
#mcclosa mentioned this as a comment but in case anyone should look at this question, see no answer and click away, the solution is to add the stats option to your webpack.config.js file as follows:
module.exports = {
stats: { children: false },
}
The above option uses the children: false option suggested by #mcclosa, which does successfully remove the junk output by mini-css-extract-plugin, but I find using the preset stats: "minimal" produces a much nicer overall output. Using:
module.exports = {
stats: "minimal",
}
..gives me the following tiny output whenever my build has no errors:
i 「wdm」: Compiling...
i 「wdm」: 69 modules
i 「wdm」: Compiled successfully.
..as opposed to dozens of lines of useless build data, but it will continue to give give error information when errors are present.
Unfortunately, mini-css-extract-loader does not have a setting to control the verbosity of its log output.
Setting stats.children to false or "minimal" in your webpack.config.js can remove a lot of other useful output like your bundle names and sizes, entry point information, time taken to build, legitimate warnings and errors from other plugins that you may want to keep, etc.
Instead it seems that we must add a plugin that executes on the compiler's done hook to remove items from the stats.compilation object associated with mini-css-extract-plugin.
This example plugin should work:
class CleanupMiniCssExtractPlugin {
apply(compiler) {
compiler.hooks.done.tap("CleanupMiniCssExtractPlugin", stats => {
if (this._children) {
const children = stats.compilation.children;
if (Array.isArray(children)) {
stats.compilation.children = children.filter(
child => child.name.indexOf("mini-css-extract-plugin") == -1
);
}
}
});
}
}
Or you can use this npm package: https://www.npmjs.com/package/cleanup-mini-css-extract-plugin
For the open source site, ReForum, I'm trying to update the site to the latest components (ie: webpack 4, react 16, etc). I started with babel and it upgraded smoothly. Then moved to webpack. I spent more than 10 hours trying various configs until I finally got it to compile using the following:
/**
* module dependencies for webpack dev configuration
* Proper webpack dev setup:
* https://medium.freecodecamp.org/how-to-develop-react-js-apps-fast-using-webpack-4-3d772db957e4
*/
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const autoprefixer = require('autoprefixer');
// define paths
const nodeModulesPath = path.resolve(__dirname, '../node_modules');
const buildPath = path.resolve(__dirname, '../public', 'build');
const mainAppPath = path.resolve(__dirname, '../frontend', 'App', 'index.js');
const sharedStylesPath = path.resolve(__dirname, '../frontend', 'SharedStyles');
const componentsPath = path.resolve(__dirname, '../frontend', 'Components');
const containersPath = path.resolve(__dirname, '../frontend', 'Containers');
const viewsPath = path.resolve(__dirname, '../frontend', 'Views');
/**
* webpack development configuration
*/
module.exports = {
mode: 'development',
target: 'web',
devtool: 'inline-source-map',
entry: [
'webpack-hot-middleware/client',
mainAppPath,
],
output: {
filename: 'bundle.js',
path: buildPath,
publicPath: '/build/',
},
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: '[name].css',
chunkFilename: '[id].css',
}),
new webpack.HotModuleReplacementPlugin(),
],
module: {
rules: [
{
test: /\.js$/,
use: [ 'babel-loader' ],
exclude: [nodeModulesPath],
},
{
test: /\.(sa|sc|c)ss$/,
use: [
'style-loader',
'css-loader',
// 'postcss-loader',
{ loader: 'postcss-loader',
options: {
sourceMap: true,
plugins() {
return [autoprefixer('last 5 version')];
},
// plugins: () => [require('autoprefixer')({
// 'browsers': ['> 1%', 'last 5 versions'],
// })],
},
},
'sass-loader',
],
},
{ test: /\.(png|jpg)$/, use: ['url-loader?limit=8192'] },
{ test: /\.svg$/, use: ['url-loader?limit=10000&mimetype=image/svg+xml'] },
],
},
resolve : {
// automatically resolve file extensions (ie import File from '../path/file')
extensions: ['.js', '.css'],
// alias to call specified folders
alias: {
SharedStyles: sharedStylesPath,
Components: componentsPath,
Containers: containersPath,
Views: viewsPath,
},
},
};
Original Webpack 1 dev config
However, the React elements classname disappear, preventing the styles from being applied. It should be like:
But instead is:
Also, the head now have multiple <style>s .
Please help me get classnames to reappear and fix the multiple head style elements.
FYI, the only way I was able to get postcss-loader to run is by turning it into an object. It would fail with errors like "Error: No PostCSS Config found in ... "
Update 1:
Tried #noppa and #Alex Ilyaev suggestions the following but it didn't work.
{
test: /\.(sa|sc|c)ss$/,
use: [
'style-loader',
// 'css-loader',
{
loader: 'css-loader',
options: {
modules: true,
loaders: true,
importLoaders: 1,
localIndentName:'[name]__[local]___[hash:base64:5]',
},
},
// 'postcss-loader',
{ loader: 'postcss-loader',
options: {
sourceMap: 'inline',
options: {
ident: 'postcss',
plugins: (loader) => [
require('autoprefixer')(),
],
},
},
},
],
},
If you're using Webpack 4, start with no config file - that's right - no config file. WP4 includes sane defaults so most of your non webpack related issues will surface right there.
Regarding the multiple styles block, you need to switch to mini-css-extract-plugin (doesn't support HMR) or extract-css-chunks-webpack-plugin (supports HMR).
Also, note that during dev mode, you'll see multiple style blocks (for HMR). But production build should not have multiple style blocks.
Here is my folder structure:
I want to minify and bundle the CSS files inside my src/css folder and output it as a single CSS file inside dist. All the examples I've seen so far recommend require-ing the CSS file inside a JS file. I do not want that. Is there a way to configure in webpack.config.js to just minify and copy these files?
Got it working.
Install dev-dependecies
npm i extract-text-webpack-plugin --save-dev
npm i css-loader --save-dev
webpack.config.js
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const extractCSS = new ExtractTextPlugin('bundle.min.css')
module.exports = {
entry: {
'bundle.min.css': [
__dirname + '/src/styles/abc.css',
__dirname + '/src/styles/xyz.css',
__dirname + '/src/styles/mno.css'
]
},
devtool: '',
output: {
path: __dirname + '/dist/styles/',
filename: '[name]'
},
module: {
rules: [{
test: /\.css$/i,
use: extractCSS.extract({
use: {
loader: 'css-loader',
options: {
minimize: true
}
}
})
}]
},
resolve: {
alias: {},
modules: [],
extensions: ['.css']
},
plugins: [
extractCSS
]
};
bundle.min.css will get generated. Based on minimize: true/false, minification will be decided. Enjoy!
It will go in three steps;
first you will need two loaders and plugin; named css-loader and style-loader and extract-text-webpack-plugin respectively.
Then your config might look like following:
const webpack = require('webpack');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const path = require('path');
module.exports = {
entry: {
app: './src/index.js'
},
output: {
path: 'dist',
filename: 'js/[name]-bundle.js'
},
devtool: "cheap-source-map",
resolveLoader: {
modules: [
'node_modules',
path.join(__dirname, '../node_modules'),
]
},
module: {
loaders: [
{
test: /.css?$/,
loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }),
exclude: /node_modules/
}
]
},
plugins: [
new ExtractTextPlugin("css/[name].css"),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
screw_ie8: true,
conditionals: true,
unused: true,
comparisons: true,
sequences: true,
dead_code: true,
evaluate: true,
join_vars: true,
if_return: true
},
output: {
comments: false
}
}),
]
}
And then in your entry file, require them like require('./style.css');
Remember, it will follow the paths as your source.
If you are loading font files and images in you css, you might need the file-loader plugin as well which will copy all assets in directory.
The file-loader config will look like:
{
test: /.png?$/,
loader: 'file-loader?name=img/[name].[ext]',
exclude: /node_modules/
}
The UgligyJsPlugin will also minify the CSS.