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
Related
Im new to react.js and currently working on a react.js project which runs 100% ok with development environment without any errors. After i build the project in production mode it will not minify my javascript files. But my scss files are get minified.
const path = require("path");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: "production",
entry: {
main: "./src/index.js",
vendor: "./src/vendor.js",
},
output: {
filename: "[name].[contentHash].bundle.js",
path: path.resolve(__dirname, "dist"),
},
module: {
rules: [
{
test: /\.html$/,
use: ["html-loader"],
},
{
test: /\.(svg|png|jpg|gif)$/,
use: {
loader: "file-loader",
options: {
name: "[name].[hash].[ext]",
outputPath: "imgs",
},
},
},
{
test: /\.scss$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
],
},
optimization: {
minimizer: [
new OptimizeCssAssetsPlugin(),
new HtmlWebpackPlugin({
template: __dirname + "/app/index.html",
minify: {
removeAttributeQuotes: true,
collapseWhitespace: true,
removeComments: true,
},
}),
],
},
plugins: [
new MiniCssExtractPlugin({ filename: "[name].[contentHash].css" }),
new CleanWebpackPlugin(),
],
};
Please someone help me to solve this problem and sorry for my bad English.
The default javascript minimizer plugin for webpack is TerserPlugin. When you setting minimizer attribute under the optimizaton, it will override the default values provided by webpack itself. To overcome this problem add TerserPlugin to your webpack.config.js file and pass it to the minimizer attribute.
const TerserPlugin = require("terser-webpack-plugin");
optimization: {
minimizer: [
new TerserPlugin(),
new OptimizeCssAssetsPlugin(),
new HtmlWebpackPlugin({
minify: {
removeAttributeQuotes: true,
collapseWhitespace: true,
removeComments: true,
},
}),
],
},
It seems like you only have minimization for your scss files, if you want to minify your javascript files aswell, you'll need a plugin such as Uglify, you just import it on the top and add it to the optimization.minimizer like it says in plugin page example:
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
optimization: {
minimizer: [new UglifyJsPlugin()],
},
};
MiniCssExtractPlugin will extract your CSS into a separate file and It creates a CSS file per JS file which contains CSS. It won't minify your CSS files.
Import css-minimizer-webpack-plugin for minification. You can configure minification based on your environment.
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const { getIfUtils } = require('webpack-config-utils')
const {ifProduction, ifNotProduction} = getIfUtils(process.env.NODE_ENV)
module.exports = {
module: {
loaders: [
{
test: /.s?css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
],
},
optimization: {
minimize: ifProduction(true, false),
minimizer: [
new CssMinimizerPlugin(),
],
},
};
Am trying to use HRM (Hot Module Replacement) in my webpack config, first I have set the --hot option within my package.jsong:
"scripts": {
"start": "webpack-dev-server --hot"
}
Also note that am using the HtmlWebpackPlugin in order to create an index.html file for me and put it in a "build" directory, here is my full webpack.config.js file:
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const WebpackManifestPlugin = require('webpack-manifest-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
// const webpack = require('webpack');
const mode = "development";
module.exports = {
mode: mode,
// watch: true,
devtool: "cheap-module-eval-source-map",
devServer: {
port: 9000,
// contentBase: path.resolve(__dirname, 'build')
},
entry: {
application: "./src/javascripts/index.js",
admin: "./src/javascripts/admin.js"
},
output: {
filename: mode === 'production' ? "[name]-[contenthash].js" : '[name].[hash].js',
path: path.resolve(__dirname, 'build'),
// publicPath: '/'
},
optimization: {
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
},
plugins: [
new MiniCssExtractPlugin({
filename: mode === 'production' ? "[name]-[contenthash].css" : "[name]-[hash].css",
hmr: mode === 'production' ? false : true
}),
new CleanWebpackPlugin(),
new WebpackManifestPlugin(),
new HtmlWebpackPlugin({
template: './src/template.html',
// filename: '../index.html'
})
// new webpack.HotModuleReplacementPlugin()
],
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
},
{
test: /\.css$/i,
use: [
MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { importLoaders: 1 } },
{
loader: 'postcss-loader',
options: {
plugins: [
require('autoprefixer')({
overrideBrowserslist: ['last 3 versions', 'ie > 9']
})
]
}
},
],
},
{
test: /\.scss$/i,
use: [
MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { importLoaders: 1 } },
{
loader: 'postcss-loader',
options: {
plugins: [
require('autoprefixer')({
overrideBrowserslist: ['last 3 versions', 'ie > 9']
})
]
}
},
'sass-loader'
],
},
{
test: /\.(png|jpg|gif|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
limit: 8192,
name: '[name].[hash:7].[ext]'
},
},
{
loader: 'image-webpack-loader'
}
],
}
]
}
}
As you see the entry I use mainly is ./src/javascripts/index.js where am importing a file called application.scss:
import application from "../stylesheets/application.scss"
the application.scss contains:
span{
background-color: blue;
}
So I want to hot reload the page whenever I change the background color of the span located in my html page.
when I run npm run start then I change the background color of the span the update works the first time (BUT IT DOES A FULL PAGE RELOAD) then if I try to change the background color again nothing get updated and all I see in the console is this:
[HMR] Nothing hot updated. log.js:24
[HMR] App is up to date.
Am not sure what am missing here, but someone can see what am doing wrong?
From the documentation,
it tries to update with HMR before trying to reload the whole page
So, presumably, if that fails, it will just reload the entire page, which is what you're seeing.
Have you tried including this at the end of your primary entry file?
if (module.hot) {
module.hot.accept(function (err) {
console.log('An error occurred while accepting new version');
});
}
Also, inspect the -hot.js file requests of network tab of Chrome's developer tools --- are they status 200, 404, 500? Maybe your server is crashing or not serving them correctly.
Ensure in your webpack that you also have
devServer: {
// contentBase: './dist', // this watches for html changes, apparently?
contentBase: path.resolve(__dirname, 'build') // in your specific case maybe?
hot: true,
},
I'm getting this error when viewing my app on IE11 and below. Also the app returns a white page.
To make things even worse, the console is not showing a line number to indicate what/where the problem is located. This makes it very hard to figure out what's wrong. I'm using Webpack 4 and babel-polyfill.
Can anyone point me in the right direction?
Webpack config
const HtmlWebPackPlugin = require("html-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const webpack = require('webpack');
const extractSass = new ExtractTextPlugin({
filename: "[name].[hash].css",
disable: process.env.NODE_ENV === "development"
});
module.exports = {
// mode: 'production',
entry: [
'babel-polyfill',
'./src/index.js'
],
output: {
publicPath: '/',
filename: '[name].[hash].js',
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [{
loader: "file-loader",
options: {
// name: "./images/[name].[hash].[ext]",
name: '[path][name]-[hash:8].[ext]'
},
}
],
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
},
{
test: /\.scss$/,
use: extractSass.extract({
use: [
{
loader: "css-loader",
options: {
minimize: true,
// sourceMap: true
}
},
{
loader: "sass-loader"
}],
// use style-loader in development
fallback: "style-loader"
})
},
{
test: /\.css$/,
use: extractSass.extract({
fallback: "style-loader",
use: "css-loader"
})
}
]
},
devServer: {
historyApiFallback: true,
contentBase: './dist',
hot: true,
},
plugins: [
extractSass,
// new ExtractTextPlugin('[name].[hash].css'),
new CopyWebpackPlugin([
{from:'src/assets/img/favicon.png',to:'src/assets/img'}
]),
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
new CleanWebpackPlugin(['dist']),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
],
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'all'
}
}
}
},
};
I want to reiterate what Jornve realized, as it took me a while to figure this out as well. The query-string package will not work in IE. As it states in the docs,
This module targets Node.js 6 or later and the latest version of Chrome, Firefox, and Safari. If you want support for older browsers, or, if your project is using create-react-app, use version 5: npm install query-string#5.
Removing the dependency and writing my own implementations of the functions fixed the problem for me. I did not try using version 5 of the package, but perhaps that would fix it too.
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.
As we are putting this output on a load balancer (not using sticky), we need to place the output of these files without chunks (neither hashes).
These are the main two files for webpack configuration.
webpack.common.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const helpers = require('./helpers');
const STATIC_TRANSLATION_MAP = require('../TranslationMap.json');
module.exports = {
entry: {
app: ['./src/public/main.ts'],
vendor: './src/public/vendor.ts',
polyfills: './src/public/polyfills.ts'
},
output: {
path: helpers.root('dist/public')
},
module: {
rules: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader', 'angular2-router-loader']
},
{
test: /\.html$/,
loader: 'html-loader?-minimize'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'file-loader?name=assets/[name].[ext]'
},
{
test: /\.styl$/,
include: helpers.root('src', 'public', 'app'),
use: [
'raw-loader',
'stylus-loader'
]
},
{
test: /\.styl$/,
include: helpers.root('src', 'public'),
exclude: helpers.root('src', 'public', 'app'),
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
'css-loader',
'stylus-loader'
]
})
},
{
test: /\.css$/,
include: helpers.root('src', 'public', 'assets', 'css'),
loader: 'raw-loader'
},
{
test: /\.xlf$/,
loader: 'raw-loader'
}
]
},
resolve: {
extensions: ['.webpack.js', '.web.js', '.ts', '.js'],
alias: {}
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: ['app', 'vendor', 'polyfills']
}),
new HtmlWebpackPlugin({
template: 'src/public/index.html'
}),
new webpack.DefinePlugin({
'process.env': {
'LOCALE_LIST': JSON.stringify(Object.keys(STATIC_TRANSLATION_MAP))
}
})
]
};
webpack.prod.js
const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const commonConfig = require('./webpack.common.js');
const helpers = require('./helpers');
const prodEnv = 'production';
module.exports = webpackMerge(commonConfig, {
devtool: 'source-map',
output: {
filename: '[name].js',
chunkFilename: '[name].js'
},
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new webpack.optimize.UglifyJsPlugin({
mangle: {
keep_fnames: true
}
}),
new webpack.LoaderOptionsPlugin({
htmlLoader: {
minimize: false
}
}),
new ExtractTextPlugin('[name].css'),
new webpack.DefinePlugin({
'process.env': {
'ENV': JSON.stringify(prodEnv)
}
})
]
});
But for my surprise, I noticed webpack is producing extra files. Can you see those ones with numbers? (From 0 to 19). I'm not sure from where they're coming from, and every content of those starts with webpackJsonp.
Is there a way to disable this chunk feature and just produce the three files from entry?
What is happening?
But for my surprise, I noticed webpack is producing extra files. Can you see those ones with numbers? (From 0 to 19)
output.chunkFilename
This option determines the name of non-entry chunk files.
By default [id].js is used or a value inferred from output.filename (name is replaced with id):
Non-entry chunks (external)
./dist/[0].js
./dist/[1].js
./dist/[2].js
./dist/[3].js
...
Entry-chunks from webpack.config.entry
./dist/app.js
./dist/vendor.js
...
How to fix it?
Currently CommonChunkPlugin only receives modules imported from entry chunks.
webpack/issues/4392
Workarounds / hacks
This concept may be used to obtain implicit common vendor chunks:
new webpack.optimize.CommonsChunkPlugin({
name: "vendor",
minChunks: function (module) {
// this assumes your vendor imports exist in the node_modules directory
return module.context && module.context.indexOf("node_modules") !== -1;
}
})
Passing the minChunks property a function
webpack/issues/2855#issuecomment-239606760
https://stackoverflow.com/a/39401288/6836839