1

After reading numerous SO questions (as well as researching online), I am still unable to generate a CSS file (with CSS inside of it) using Webpack 2 (v2.1.0-beta.27), ExtractText plugin (v2.0.0-beta.4), sass-loader (v3.2.0), css-loader (v0.26.1), and style-loader (v0.13.1).

Currently Webpack 2 completes successfully and generates my JS files as expected, but my app.css file is empty (Chrome throws a 404 for the file) but is generated in the correct location according to my Sources panel in Chrome. This leads me to believe there is an issue with css-loader or another loader.

My current webpack.config.js file looks like this:

const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const autoprefixer = require('autoprefixer');
const path = require('path');
const resolve = path.resolve;

const rootDir = resolve(__dirname);
const dist = resolve(rootDir, 'coolAppName/secured_assets');
const assetIndex = resolve(rootDir, 'src/app');
const vendorIndex = resolve(rootDir, 'webpack.vendor.js');
const styleIndex = resolve(rootDir, 'webpack.style.js');
const fontPath = '../static/fonts/';

module.exports = {

  watchOptions: {
    poll: 3000,
    aggregateTimeout: 1000,
  },

  devServer: {
    port: 8080,
    publicPath: 'http://localhost:8080/secured_assets/',
  },

  devtool: 'eval-source-map',

  entry: {
    app: assetIndex,
    style: styleIndex,
    vendor: vendorIndex,
  },

  output: {
    path: dist,
    filename: '[name].js',
    publicPath: 'http://localhost:8080/secured_assets/'
  },

  module: {
    loaders: [

      // CSS files
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract({
          fallbackLoader: 'style-loader',
          loader: [
            {
              loader: 'css-loader',
            }
          ]
        }),
      },

      // SCSS files
      {
        test: /\.scss$/,
        loader: ExtractTextPlugin.extract({
          fallbackLoader: 'style-loader',
          loader: [
            {
              loader: 'css-loader'
            },
            {
              loader: 'sass-loader'
            }
          ]
        })
      },

      {
        test: /\.(gif|png)$/,
        loaders: [
          {
            loader: 'url-loader',
            query: {
              mimetype: 'image/png'
            },
          },
        ],
      },

      {
        test: /\.js/,
        loaders: 'babel-loader',
        include: [
          assetIndex,
        ],
        exclude: /(node_modules|bower_components)/,
        query: {
          cacheDirectory: true,
        },
      },      

      {
        test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loaders: 'url-loader',
        query: {
          limit: 10000,
          mimetype: 'application/font-woff',
          name: `${fontPath}[name].[ext]`,
        },
      },

      {
        test: /\.(ttf|eot|svg|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loaders: 'file-loader',
        query: {
          name: `${fontPath}[name].[ext]`,
        },
      },

      {
        test: /\.json$/,
        loaders: 'json-loader',
      },

      {
        test: /\.html$/,
        loaders: 'html-loader',
      },

    ],
  },

  plugins: [
    new ExtractTextPlugin({
      filename: '/css/app.css',
      allChunks: true,
    })
  ],

};

and my webpack.style.js file looks like this:

// STYLE entrypoint
// vendor (CSS)
require('./coolAppName/static/fonts/custom-font-icons/styles.css');
require('font-awesome/css/font-awesome.css');
require('simple-line-icons/css/simple-line-icons.css');
require('lato-font');
require('./node_modules/bootswatch/yeti/bootstrap.min.css');
require('./node_modules/angularjs-toaster/toaster.css');
require('./node_modules/angular-busy2/dist/angular-busy.css');
require('./node_modules/perfect-scrollbar/dist/css/perfect-scrollbar.css');
require('./node_modules/angular-bootstrap-lightbox/dist/angular-bootstrap-lightbox.css');
require('./node_modules/angularjs-slider/dist/rzslider.min.css');
require('./node_modules/ui-select/dist/select.css');
require('./coolAppName/static/fonts/noto/noto.css');
// SCSS
require('./src/app/css/templates.scss');

My file structure looks like this (which is correct):

file structure

Before trying to migrate to Webpack 2, everything was working as expected. The only thing that has changed are related to Webpack 2 upgrades, all file pathing and the loaders I am using are the same (except for upgrading the versions).

This is what the important sections looked like with Webpack 1 (I got rid of postcss-loader for this example above)

{
    test: /\.css$/,
    loader: ExtractTextPlugin.extract('style-loader', 'css-loader?sourceMap!postcss-loader'),
},
{
    test: /\.scss$/,
    loader: ExtractTextPlugin.extract('style-loader', 'css-loader?sourceMap!sass-loader?sourceMap!postcss-loader'),
},

Ultimately I want to create 1 CSS file within /secured_assets/css/app.css that contains all of the styles I require in webpack.style.js. At this point, I get no errors and the app.css has no contents and I see a 404 in my Network panel (although it shows up in Sources in Chrome).

Update

When I simply run webpack --config ./webpack.dev.js it creates my app.css correctly. When I run webpack-dev-server --config ./webpack.dev.js it does not. So looks to be a possible webpack-dev-server issue...

Community
  • 1
  • 1
james
  • 5,006
  • 8
  • 39
  • 64

2 Answers2

0

You should use the query parameter importLoaders (doc: importing and chained loaders):

// SCSS files
{
  test: /\.scss$/,
  loader: ExtractTextPlugin.extract({
    fallbackLoader: 'style-loader',
    loader: [
      {
        loader: 'css-loader',
        query: {
          importLoaders: 1
        }
      },
      {
        loader: 'sass-loader'
      }
    ]
  })
}
Kévin Berthommier
  • 1,402
  • 15
  • 15
  • This didn't do the trick unfortunately. Although this is certainly useful, thanks for pointing it out. – james Dec 08 '16 at 14:51
0

The issue was a slash (/) prefixed to ExtractTextPlugin's filename in my plugins array.

Before:

new ExtractTextPlugin({
  filename: '/css/app.css',
  allChunks: true,
})

After:

new ExtractTextPlugin({
  filename: 'css/app.css',
  allChunks: true,
})

webpack-dev-server was able to properly locate this file after making this change.

james
  • 5,006
  • 8
  • 39
  • 64