webpacksasssass-loaderextract-text-plugin

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


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

├── babel-cli@6.26.0
├── babel-loader@7.1.2
├── babel-plugin-transform-class-properties@6.24.1
├── babel-polyfill@6.26.0
├── babel-preset-es2015@6.24.1
├── babel-preset-stage-3@6.24.1
├── css-loader@0.28.7
├── extract-text-webpack-plugin@3.0.0
├── html-loader@0.5.1
├── html-webpack-plugin@2.30.1
├── markdown-loader@2.0.1
├── node-sass@4.5.3
├── sass-loader@6.0.6
├── style-loader@0.18.2
├── webpack@3.5.6
└── webpack-dev-server@2.7.1

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
        }
    }
};

Solution

  • 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.