2

Introduction

I have already setup bundling for my Javascript files with webpack in my project. Now I am in the process of adding CSS files to the webpack configuration. So far, I have been including the CSS files manually in the HTML header by adding <link> elements for every CSS file I depend on (e.g. bootstrap, my own css, etc.). Obviously this is not very elegant and using webpack would be much better, so I would like to replace the link elements and bundle them via webpack.

This should be easy, everything is pretty much documented in the webpack documentation. After reading the documentation and experimenting a bit with webpack I have arrived at the configuration below which already works.

Problem

The problem with my current setup is that I would like to have proper source map support and that does not seem to work. By proper, I mean that I expect that when I run a development build with webpack and I inspect some element in Chrome DevTools, that I will see from which file and which line in the file a certain CSS class originated and that I can click on the CSS rules and the browser jumps to that file.

I do not want to have inline styles in the head element, because then the browser will show something like .foobar { <style>..</style>, rather then .foobar { app.css:154.

With my current setup I have all CSS files combined (but not minified) into one app.css file. This means that if I inspect a bootstrap class such as .btn then it appears as .btn { app.css:3003. However, what I want to achieve is that the browser shows it as .btn { bootstrap.css:3003.

So now I am trying to understand how webpack and the different plugins such as css-loader and min-css-extract-plugin apply CSS source maps, and how I can configure them to achieve a proper debugging experience.

I am not sure how relevant this is, but when I navigate in DevTools under Sources to webpack://./bootstrap/dist/css/bootstrap.css I see that it only contains a single line: // extracted by mini-css-extract-plugin.

Webpack Setup

index.js:

window.jQuery = require('jquery/dist/jquery');
require('bootstrap/dist/css/bootstrap.css');
require('bootstrap/dist/js/bootstrap');
/* other dependencies */

webpack.config.js:

const devMode = process.env.NODE_ENV !== 'production';

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module: {
    rules: [ 
        { /* Javascript rules excluded */ },
        {
            test: /\.css$/,

            use: [
                {
                    loader: MiniCssExtractPlugin.loader
                },
                {
                    loader: 'css-loader',

                    options: {
                        sourceMap: true
                    }
                }
            ]
        },
        {
            test: /\.(png|svg|jpg|gif)$/,

            use: [
                'file-loader'
            ]
        },
        {
            test: /\.(woff|woff2|eot|ttf|otf)$/,
            use: [
                'file-loader'
            ]
        }
plugins: [
    new UglifyJSPlugin (),
    new HtmlWebpackPlugin({
                              template: 'app/index.tpl.html'
                          }),
    new MiniCssExtractPlugin({ filename: devMode ? 
                               '[name].css' :
                               '[name].[hash].css' 
                             })
],

Conclusion

It seems I just passed the rubber duck test. While I was writing this I arrived at a solution. I will still publish the question, maybe it can help others.

1 Answer 1

1

The problem was that I was also using the mini-css-extract-plugin for development and not just for production. I thought that I needed to do that, because when at first I was using the style-loaded I would get styles included in the header and the browser would show me all styles as .foobar { <style>..</style>.

However, the actual problem seemed to be, that I was not using devtools. So the solution was to add devtool: devMode ? 'cheap-module-eval-source-map' : 'source-map', to the webpack configuration to conditionally use the style-loader plugin during development builds and mini-css-extract-plugin during production builds.

webpack.config.js

        {
            test: /\.css$/,

            use: [
                {
-                   loader: MiniCssExtractPlugin.loader,
+                   loader: devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
                },
                {
                    loader: 'css-loader',

                    options: {
                        sourceMap: true
                    }
                }
            ]
        },

  /* ... */

+ devtool: devMode ? 'cheap-module-eval-source-map' : 'source-map',
Sign up to request clarification or add additional context in comments.

1 Comment

No longer works with webpack 5.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.