0

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

Yaron
  • 1,655
  • 6
  • 20
  • 38

1 Answers1

1

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!

Nathan
  • 7,853
  • 4
  • 27
  • 50
  • How do I specify an entry point for the MiniCssExtractPlugin ? I I thought I should include all my entry points in one place ("entry") and just test for the right loader using 'rules'. Thanks for your help. – Yaron Mar 10 '19 at 19:12
  • Yes you're correct but the issue lies in how you're creating your unique bundles. What I would do is create a main.scss file which simply imports all your other sass files for your project. Then add this file into your entry list and when the MiniCssExtractPlugin runs it will export all this styling into an equivalent css file given by the filename specified within the filename key. – Nathan Mar 10 '19 at 19:23
  • So there is no way to use webpack to create multiple .scss bundles - one for each page ? – Yaron Mar 10 '19 at 19:26
  • Yes there is, use the [name] parameter and add each .scss file which you wish to be a bundle as an entry point. Then simply ensure each .scss file included as an entry point is uniquely named. Maybe this could be a useful resource: https://hackernoon.com/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758 – Nathan Mar 10 '19 at 19:41
  • But that was my initial setup.. a list of entry points, some '.ts' and some '.scss', all of them uniquely named. I just need my .ts files to bundle to a '.js' and my 'scss' to bundle to a '.css'. – Yaron Mar 10 '19 at 20:02
  • Please reread over my answer as I have outlined that use case exactly: a single js bundle and a single css file to be included in your index file. What you currently do is create a bundle on a per file basis... so you get a bundle per entry point. I have pointed out how to chunk your application into multiple bundles if desired as well as a single js bundle and css file – Nathan Mar 10 '19 at 20:11
  • 1
    I didn't understand that you meant including the corresponding .scss file as an import for each of the .ts entrypoints.. That works, thank you ! – Yaron Mar 10 '19 at 23:33