webpack-contrib / sass-loader

Compiles Sass to CSS
MIT License
3.9k stars 427 forks source link

After upgrading from 7.2.0 to 7.3.1 my webpack always minifies CSS? #785

Closed Friends-for-Brands closed 4 years ago

Friends-for-Brands commented 4 years ago

Expected Behavior

I Would like to upgrade to the latest possible sass-loader and be able to minify in production mode only and development should be uncompressed.

Actual Behavior

After upgrading sass-loader from 3.1.0 to 3.2.1 sass-loader always minifies CSS even in production and development mode.

Code

require('checkenv').check();

// Webpack Setup
const {
    THEME_AUTHOR,
    THEME_NAME,
    ASCII_TEXT,
    ASCII_FONT,
    HOST,
    PORT
} = require('./env.config');

const path = require('path');
const paths = require('./paths.config');
const pkg = require('../package.json');
const webpack = require('webpack');
const date = new Date();

// Plugins
const HappyPack = require('happypack');
const DashboardPlugin = require('webpack-dashboard/plugin');
const { AsciiArtWebpackPlugin } = require('ascii-art-webpack-plugin');
const ImageminWebpWebpackPlugin = require('imagemin-webp-webpack-plugin');
const HardSourceWebpack = require('hard-source-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const BrowserSync = require('browser-sync-webpack-plugin');
const MiniCssExtract = require('mini-css-extract-plugin');
const styleLint = require('stylelint-webpack-plugin');
const CopyWebpack = require('copy-webpack-plugin');
const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin');
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
const WebpackBuildNotifierPlugin = require('webpack-build-notifier');
const CleanTerminalPlugin = require('clean-terminal-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const Imagemin = require('imagemin-webpack-plugin').default;
const threadPool = HappyPack.ThreadPool({ size: 4 });

// Config utils
const { removeEmpty, getIfUtils } = require('webpack-config-utils');
const { NODE_ENV } = process.env;
const { ifProduction, ifDevelopment } = getIfUtils(NODE_ENV);

module.exports = {
    target: 'web',
    mode: ifDevelopment ? 'development' : 'production',

    stats: {
        colors: false,
        hash: false,
        version: false,
        timings: false,
        assets: false,
        chunks: false,
        modules: false,
        reasons: false,
        children: false,
        source: false,
        errors: false,
        builtAt: false,
        errorDetails: false,
        entrypoints: false,
        warnings: false,
        publicPath: false
    },

    optimization: {
        minimize: ifProduction(true, false),
        namedModules: ifDevelopment(true, false),
        runtimeChunk: 'single',
        noEmitOnErrors: true,
        splitChunks: {
            hidePathInfo: true,
            chunks: 'all',
            automaticNameDelimiter: '-',
            maxAsyncRequests: 5,
            maxInitialRequests: 3,
            name: THEME_NAME,
            cacheGroups: {
                style: {
                    enforce: true,
                    priority: 1
                },
                vendors: {
                    test: /[\\/]node_modules[\\/]/,
                    priority: 2,
                    name: 'vendors',
                    enforce: true,
                    chunks: 'all'
                }
            }
        },

        minimizer: [
            new TerserPlugin({
                test: /\.js(\?.*)?$/i,
                cache: true,
                parallel: 4,
                sourceMap: ifDevelopment(true, false),
                extractComments: false,
                terserOptions: {
                    compress: {
                        drop_console: ifProduction(true, false)
                    }
                },
                exclude: /\/node_modules/
            })
        ]
    },

    entry: {
        src: [paths.entry.js(), paths.entry.sass()]
    },

    output: {
        path: paths.output.base(),
        filename: paths.filename.js()
    },

    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loaders: ['happypack/loader?id=js']
            },

            {
                test: /\.scss$/,
                exclude: /node_modules/,
                loaders: [MiniCssExtract.loader, 'happypack/loader?id=scss']
            }
        ]
    },

    plugins: removeEmpty([
        new CleanWebpackPlugin({
            // Write Logs to Console
            verbose: ifDevelopment(true, false),

            // Automatically remove all unused webpack assets on rebuild
            cleanStaleWebpackAssets: false,

            // Do not allow removal of current webpack assets
            protectWebpackAssets: false
        }),

        new ExtraWatchWebpackPlugin({
            files: ['.stylelintrc', '.eslintrc']
        }),

        new HappyPack({
            id: 'js',
            verbose: ifDevelopment(true, false),
            threadPool: threadPool,
            loaders: ['babel-loader', 'eslint-loader']
        }),

        new HappyPack({
            id: 'scss',
            verbose: ifDevelopment(true, false),
            threadPool: threadPool,
            loaders: [
                {
                    loader: 'css-loader',
                    options: {
                        url: false,
                        modules: false
                    }
                },
                'postcss-loader',
                'sass-loader'
            ]
        }),

        new styleLint({
            configFile: '.stylelintrc',
            context: paths.sass(),
            files: '**/*.s?(a|c)ss'
        }),

        new MiniCssExtract({
            filename: paths.filename.sass()
        }),

        new DashboardPlugin(),

        new CopyWebpack([
            {
                from: paths.images(),
                to: paths.output.images()
            }
        ]),

        new CopyWebpack([
            {
                from: paths.fonts(),
                to: paths.output.fonts()
            }
        ]),

        ifProduction(
            new ImageminWebpWebpackPlugin({
                config: [
                    {
                        test: /\.(jpe?g|png)/,
                        options: {
                            quality: 75
                        }
                    }
                ],
                overrideExtension: true,
                detailedLogs: true,
                silent: false,
                strict: true
            })
        ),

        ifProduction(
            new Imagemin({
                test: /\.(jpe?g|png|gif|svg)$/i
            })
        ),

        new AsciiArtWebpackPlugin({
            text: ASCII_TEXT,
            font: ASCII_FONT,
            extensions: ['js', 'css']
        }),

        new HardSourceWebpack.ExcludeModulePlugin([
            {
                // HardSource works with mini-css-extract-plugin but due to how
                // mini-css emits assets, assets are not emitted on repeated builds with
                // mini-css and hard-source together. Ignoring the mini-css loader
                // modules, but not the other css loader modules, excludes the modules
                // that mini-css needs rebuilt to output assets every time.
                test: /mini-css-extract-plugin[\\/]dist[\\/]loader/
            },
            {
                test: /my-loader/,
                include: path.join(__dirname, 'vendor')
            }
        ]),

        new HardSourceWebpack({
            environmentHash: {
                root: process.cwd(),
                directories: [],
                files: ['package-lock.json', 'yarn.lock']
            },

            info: {
                mode: 'none',
                level: 'debug'
            },

            // Clean up large, old caches automatically.
            cachePrune: {
                // Caches younger than `maxAge` are not considered for deletion. They must
                // be at least this (default: 2 days) old in milliseconds.
                maxAge: 2 * 24 * 60 * 60 * 1000,
                // All caches together must be larger than `sizeThreshold` before any
                // caches will be deleted. Together they must be at least this
                // (default: 50 MB) big in bytes.
                sizeThreshold: 50 * 1024 * 1024
            }
        }),

        new BrowserSync(
            {
                proxy: HOST,
                port: PORT,
                host: 'localhost',
                open: false,
                notify: false,
                logFileChanges: false,
                logLevel: 'info',
                // files: [`../**/*.scss`, `../**/*.php`],
                files: [
                    {
                        match: [
                            // '../assets/css/*.css',
                            // '../assets/js/*.js',
                            '../**/*.php'
                        ],
                        fn: (event, file) => {
                            if (event == 'change') {
                                const bs = require('browser-sync').get(
                                    'bs-webpack-plugin'
                                );
                                if (
                                    file.split('.').pop() == 'js' ||
                                    file.split('.').pop() == 'php'
                                ) {
                                    bs.reload();
                                } else {
                                    bs.reload('*.css');
                                }
                            }
                        }
                    }
                ],
                snippetOptions: {
                    ignorePaths: ['wp-admin/**', 'wp-content/**']
                }
            },

            {
                reload: false
            }
        ),

        new FriendlyErrorsPlugin(),

        new CleanTerminalPlugin(),

        new webpack.optimize.ModuleConcatenationPlugin(),

        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify(NODE_ENV),
            'process.env.VERSION': JSON.stringify(pkg.version)
        }),

        new webpack.optimize.OccurrenceOrderPlugin(true),

        new webpack.BannerPlugin({
            banner: `Copyright ${date.getFullYear()} ${THEME_AUTHOR} All Rights Reserved - v${
                pkg.version
            }\nLast updated: ${date.getDate()}/${date.getMonth() +
                1}/${date.getFullYear()} (${date.getHours()}:${(
                '0' + date.getMinutes()
            ).substr(-2)})`,
            exclude: /(main-vendor|main-runtime)\.js/i
        }),

        ifDevelopment(new webpack.HashedModuleIdsPlugin()),

        ifDevelopment(
            new webpack.SourceMapDevToolPlugin({
                exclude: /(main-vendor|main-runtime)\.js/i
            })
        ),

        ifDevelopment(
            new WebpackBuildNotifierPlugin({
                title: `${THEME_AUTHOR}`,
                sound: false,
                suppressSuccess: true
            })
        )
    ])
};

Thanks in advance.

alexander-akait commented 4 years ago

We don't minify your css, please look at code and you don't find places where we minified code, you can try to change outputStyle https://github.com/sass/node-sass#outputstyle, but problem not in sass-loader, no minification on our side, we only use compressed output style in production mode https://github.com/webpack-contrib/sass-loader/blob/master/src/getSassOptions.js#L69

Friends-for-Brands commented 4 years ago

We don't minify your css, please look at code and you don't find places where we minified code, you can try to change outputStyle https://github.com/sass/node-sass#outputstyle, but problem not in sass-loader, no minification on our side, we only use compressed output style in production mode https://github.com/webpack-contrib/sass-loader/blob/master/src/getSassOptions.js#L69

Easy to say... It works perfectly in 3.2.0?

alexander-akait commented 4 years ago

What is mean 3.2.0?

alexander-akait commented 4 years ago

3.2.0 is deprecated and doesn't work as expected, please use latest verison https://github.com/webpack-contrib/sass-loader/blob/master/package.json#L3

Friends-for-Brands commented 4 years ago

What is mean 3.2.0?

sass-loader version 3.2.0 compiles in production mode & development is not minified. Upgrading to 3.2.1 minimizes CS in production and development. That's why I have asked this question.

alexander-akait commented 4 years ago

What is 3.2.1? sass-loader very long time not using these versions