Webpack 3: Use sass-loader and ExtractTextPlugin doesn't work

5k views Asked by At

I've been trying to use the sass-loader in webpack and I follow this instructions -> https://github.com/webpack-contrib/extract-text-webpack-plugin#extracting-sass-or-less but this not working.

Can anybody help me?

Repository

https://github.com/gpincheiraa/boolean-html-js-exercises/tree/dev

Error

ERROR in   Error: Child compilation failed:
  Module build failed: Error: "extract-text-webpack-plugin" loader is used without the corresponding plugin, refer to https://github.com/webpack/extract-text-webpack-plugin for the usage example

  - Error: "extract-text-webpack-plugin" loader is used without the corresponding plugin, refer to https://github.com/webpack/extract-text-webpack-plugin for the usage example

Dependencies

node v6.11.1
npm 5.3.0

├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
    entry: [
      "./index.js"
    ],
    output: {
        path: __dirname + "/dist",
        filename: "index.bundle.js"
    },
    module: {
        rules: [
            { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" },
            { test: /\.md$/, loaders: [ "html-loader", "markdown-loader" ] },
            { test: /\.scss$/,
              use: ExtractTextPlugin.extract({
                  fallback: 'style-loader',
                  use: ['css-loader', 'sass-loader']
              })
            }
        ]
    },
    plugins: [
        new ExtractTextPlugin('style.css'),
        new HtmlWebpackPlugin({
          template: 'index.html',
          inject: 'body'
        })
    ],
    devtool: "eval-source-map",
    devServer: {
        filename: "index.bundle.js",
        contentBase: "./",
        port: 3000,
        publicPath: "/",
        stats: {
            colors: true
        }
    }
};
2

There are 2 answers

2
Michael Jungo On BEST ANSWER

The issue comes from the commented style code in your index.html. The index.html is processed by the html-webpack-plugin and for some reason it still tries to process the require calls (line 9 and line 11). The reason could be the custom EJS loader of html-webpack-plugin.

The easiest solution is to fully remove the commented code from index.html.

By importing a .scss file, the rule you configured gets applied to it. But it seems that the actual extract-text-webpack-plugin instance isn't available during that process. You are using an inline loader in these require calls, but your configured rules will still be applied to that. To prevent other loaders from being applied, you can prefix the import with a !.

From the webpack documentation - Rule.enforce:

All normal loaders can be omitted (overridden) by prefixing ! in the request.

All normal and pre loaders can be omitted (overridden) by prefixing -! in the request.

All normal, post and pre loaders can be omitted (overridden) by prefixing !! in the request.

To be able to use the CSS correctly in your HTML you'll also need to use css-loader after the sass-loader, because EJS expects JavaScript at this place, not bare CSS. The require would become:

<%= require("!css-loader!sass-loader!\./sass/index.scss") %>

It would also be better to import index.scss in your actual application instead of the template that is used by html-webpack-plugin.

0
R01010010 On

I came here because my configuration with Webpack 3 + Sass + React wasn't working either.

However, in my case the problem was very stupid. I must say I created the project with create-react-app tool and it sets a webpack.config.dev.js file with a quiet complex/complete configuration.

The problem was that I was adding the sass rule AFTER the exclude one and it clearly says in the comments (hah) that every loader after that one will not work.

So it looks now like this and it works:

      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [require.resolve('css-loader'), require.resolve('sass-loader')],
        })
      },
      {
        exclude: [/\.js$/, /\.html$/, /\.json$/],
        loader: require.resolve('file-loader'),
        options: {
          name: 'static/media/[name].[hash:8].[ext]',
        },
      },

Hope this helps someone in the future.