Exclude some css files in webpack

Timmy Mucks picture Timmy Mucks · Mar 22, 2019 · Viewed 12.4k times · Source

I'm facing a problem with webpack. My project has the following structure.

Folder structure:

src
  js
    app.js  // For importing app.scss file
    vendor.js // For importing vendor.scss file
  scss
    app.scss // Our custom styles
    vendor.scss // Require all vendor styles from node_modules
package.json
postcss.config.js
webpack.config.js

Inside scss folder there are 2 files app.scss & vendor.scss. app.scss file contains all our custom styles, vendor.scss file contains all vendor styles such as bootstrap library styles.

After webpack command:

npm run dev

Webpack import these scss files through JavaScript files and add vendor prefixes via postcss-loader and output on a dist folder.

But I don't want to add vendor prefixes on vendor.scss file because the vendor library already has vendor prefixes. So is there a way to exclude vendor.scss file from postcss-loader.

Full Code:

src/js/app.js:

import '../scss/app.scss'

src/js/vendor.js:

import '../scss/vendor.scss'

src/scss/app.scss:

// Our custom styles
.app {
  display: flex;
}

src/scss/vendor.scss:

// Vendor Styles
.container {
  display: flex;
}

@import '~bootstrap/scss/bootstrap';

package.json:

{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack --mode development --progress true --colors"
  },
  "author": "",
  "license": "MIT",
  "dependencies": {
    "bootstrap": "^4.2.1"
  },
  "devDependencies": {
    "@babel/core": "^7.2.2",
    "@babel/preset-env": "^7.3.1",
    "autoprefixer": "^9.4.6",
    "babel-loader": "^8.0.5",
    "css-loader": "^2.1.0",
    "filemanager-webpack-plugin": "^2.0.5",
    "mini-css-extract-plugin": "^0.5.0",
    "node-sass": "^4.11.0",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^7.1.0",
    "webpack": "^4.29.0",
    "webpack-cli": "^3.2.1"
  }
}

postcss.config.js:

module.exports={
  plugins: [
    require('autoprefixer')({
      'browsers': [
        '>= 1%',
        'last 1 major version',
        'not dead',
        'Chrome >= 45',
        'Firefox >= 38',
        'Edge >= 12',
        'Explorer >= 10',
        'iOS >= 9',
        'Safari >= 9',
        'Android >= 4.4',
        'Opera >= 30'
      ],
      cascade: true
    })
  ]
};

webpack.config.js:

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const FileManagerPlugin = require('filemanager-webpack-plugin');
module.exports = function() {
    return ({
        entry: {
            'vendor': './src/js/vendor.js',
            'app': './src/js/app.js',
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: 'js/[name].[chunkhash].js'
        },
        module: {
            rules: [{
                    test: /\.js$/,
                    exclude: /(node_modules)/,
                    use: {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-env']
                        }
                    }
                },
                {
                    test: /\.(sa|sc|c)ss$/,
                    use: [{
                            loader: MiniCssExtractPlugin.loader,
                            options: {
                                publicPath: '../'
                            }
                        }, {
                            loader: 'css-loader',
                        }, // translates CSS into CommonJS
                        {
                            loader: 'postcss-loader',
                        }, // Add vendor prefixes on build css file
                        {
                            loader: 'sass-loader',
                        } // compiles Sass to CSS
                    ]
                },
            ]
        },
        plugins: [
            new MiniCssExtractPlugin({
                filename: 'css/[name].[contenthash].css'
            }),
            // Before Build
            new FileManagerPlugin({
                onStart: {
                    delete: [
                        'dist',
                    ],
                }
            }),
        ]
    });
};

Zip file.

Answer

Ahmad Hussnain picture Ahmad Hussnain · Mar 22, 2019

So you want vendor prefixes don't add on Webpack generated vendor.css file.

Remember Webpack parse loader array on reverse order. You could add exclude property on the object of postcss-loader with the regular expression.

webpack.config.js:

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const FileManagerPlugin = require('filemanager-webpack-plugin');
module.exports = function() {
    return ({
        entry: {
            'vendor': './src/js/vendor.js',
            'app': './src/js/app.js',
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: 'js/[name].[chunkhash].js'
        },
        module: {
            rules: [{
                    test: /\.js$/,
                    exclude: /(node_modules)/,
                    use: {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-env']
                        }
                    }
                },
                {
                    test: /\.s(c|a)ss$/,
                    use: {
                        loader: MiniCssExtractPlugin.loader,
                        options: {
                            publicPath: '../'
                        }
                    },// Take scss file and split into a separate css file
                },
                {
                    test: /\.s(c|a)ss$/,
                    use: {
                        loader: 'css-loader',
                    },// Interprets scss @import and url() like import/require()
                },
                {
                    test: /\.s(c|a)ss$/,
                    exclude: [/vendor/],
                    use: {
                        loader: 'postcss-loader',
                    },
                }, // PostCSS turns your SCSS file into a JS object & converts that object back to a SCSS file
                {
                    test: /\.s(c|a)ss$/,
                    use: {
                        loader: 'sass-loader',
                    },// look for scss file through sass-loader, compile scss into css code
                },
            ]
        },
        plugins: [
            new MiniCssExtractPlugin({
                filename: 'css/[name].[contenthash].css'
            }),
            // Before Build
            new FileManagerPlugin({
                onStart: {
                    delete: [
                        'dist',
                    ],
                }
            }),
        ]
    });
};