Search code examples
webpackmini-css-extract-plugin

Webpack SCSS config


I have the following webpack setup:

let config= {
    mode: 'development',
    entry:  {
        'templates': '/usr/local/var/www/project/src/ts/entry/templates.ts',
        'templates2': '/usr/local/var/www/project/src/ts/entry/templates2.ts',
        'main_scss': '/usr/local/var/www/project/src/sass/entry/main_scss.scss',
        'templates': '/usr/local/var/www/project/src/sass/entry/templates.scss'
    },
    output: {
        path:  path.resolve(__dirname, 'public/assets'),
        filename: '[name].bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.(ts)$/,
                use: [
                    'ts-loader',
                ],
            },
            {
                test: /\.(scss)$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'sass-loader',
                ],

            },
        ]
    },
    plugins:[
        new MiniCssExtractPlugin({
            filename: "[name].css",
        })
    ]


};

The result is a folder with a .js file for each .ts file and 2 files for each .scss file. (main_scss.scss results in main_scss.bundle.js and main_scss.css)

Why? I would like the .scss files to be bundled into .css only.

Thanks Yaron


Solution

  • This is because you have specified to have multiple output bundles, namely one bundle per each entry point. Additionally, each bundle is to be uniquely named, based on each entry point's filename, as specified with this line of code:

    filename: '[name].bundle.js'.

    '[name]' will dynamically substitute the underlying filename for each entry point namely: templates, templates2, main_scss, and templates (for your styling) and concatenate this with with 'bundle.js' resulting in multiple uniquely named bundles, namely:

    1. templates.bundle.js
    2. templates2.bundle.js
    3. main_scss.bundle.js

    For an in-depth explanation on how output bundles are created check out Webpack's documentation for output bundles.

    With that being said, you get a main_scss.bundle.js from my above mentioned explanation and you get a main_scss.css styling file from your MiniCssExtractPlugin plugin. MiniCssExtractPlugin is extracting your SASS files and converting them into an equivalent CSS file. You're specifying this SASS to CSS extraction with this line of code:

    plugins:[
            new MiniCssExtractPlugin({
                filename: "[name].css",
            })
        ]
    

    Note that [name] is used here again so each generated CSS file will also be uniquely named based on the underlying filename for each SASS file. If you just want the bundle to include your JavaScript files and to generate a single CSS file, I would try the following:

    1. Create a single bundle that isn't uniquely named based on each entry point's filename, something like the following:

      output: { path: path.resolve(__dirname, 'public/assets'), filename: 'bundle.js' },

    2. Remove the multiple CSS entry points and instead create a single main.scss file. This file sole purpose will to be to import all your project's other SASS files.

    3. Add this file created in step 2 as an entry point.

    This will result in a single JavaScript bundle: bundle.js and a single CSS file: main.css which will contain all your application's JavaScript and styling respectively. You can them simply link your generated JavaScript bundle and corresponding CSS file within your index.html page.

    Hopefully that helps!