window not defined error when using extract-text-webpack-plugin React

ReactjsWebpack

Reactjs Problem Overview


I'm using webpack to build my react components and I'm trying to use the extract-text-webpack-plugin to separate my css from my generated js file. However, when I attempt to build the component I get the following error: Module build failed: ReferenceError: window is not defined.

My webpack.config.js file looks like this:

var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  entry: {
    MainComponent: './src/main.js'
  },
  output: {
    libraryTarget: 'var',
    library: 'MainComponent',
    path: './build',
    filename: '[name].js'
  },
  module: {
    loaders: [{
      test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader!css-loader')
    }]
  },
  plugins: [
    new ExtractTextPlugin('styles.css')
  ]
}

Reactjs Solutions


Solution 1 - Reactjs

You may want to use style-loader as a before argument in extract function.

Here's the native implementation:

	ExtractTextPlugin.extract = function(before, loader, options) {
		if(typeof loader === "string") {
			return [
				ExtractTextPlugin.loader(mergeOptions({omit: before.split("!").length, extract: true, remove: true}, options)),
				before,
				loader
			].join("!");
		} else {
			options = loader;
			loader = before;
			return [
				ExtractTextPlugin.loader(mergeOptions({remove: true}, options)),
				loader
			].join("!");
		}
	};

So basicaly what you need to do is:

{
    test: /\.sass$/,
    exclude: /node_modules/,
    loader: ExtractTextPlugin.extract('style-loader', 'css!sass?indentedSyntax=true&sourceMap=true')
},

if you for example use sass.

Solution 2 - Reactjs

Didn't see an explanation of the cause so I have posted this answer here.

From https://github.com/webpack/extract-text-webpack-plugin#api

> ExtractTextPlugin.extract([notExtractLoader], loader, [options]) > Creates an extracting loader from an existing loader. > > notExtractLoader (optional) the loader(s) that should be used when the css is not extracted (i.e. in an > additional chunk when allChunks: false) > > loader the loader(s) that should be used for converting the resource to a css exporting module. > > options > > publicPath override the publicPath setting for this loader.

The #extract method should receive a loader that outputs css. What was happening was that it was receiving a style-loader which outputs javascript code, which is intended to be injected into a webpage. This code would try to access window.

You should not pass a loader string with style to #extract. However...if you set allChunks=false, then it will not build CSS files for non-initial chunks. Therefore it needs to know what loader to use to inject into the page.

Tip: Webpack is a tool that really needs to be understood in-depth or you can run into lots of strange issues.

Solution 3 - Reactjs

Webpack 2

If you're using Webpack 2, this variation works:

    rules: [{
        test: /\.css$/,
        exclude: '/node_modules/',
        use: ExtractTextPlugin.extract({
            fallback: [{
                loader: 'style-loader',
            }],
            use: [{
                loader: 'css-loader',
                options: {
                    modules: true,
                    localIdentName: '[name]__[local]--[hash:base64:5]',
                },
            }, {
                loader: 'postcss-loader',
            }],
        }),
    }]

The new extract method no longer takes three arguments, and is listed as a breaking change when moving from V1 to V2.

https://webpack.js.org/guides/migrating/#extracttextwebpackplugin-breaking-change

Solution 4 - Reactjs

I figured out the solution to my problem:

Instead of piping the loaders into one another (ExtractTextPlugin.extract('style-loader!css-loader')), you have to pass in the each loader as a separate parameter: ExtractTextWebpackPlugin.extract('style-loader', 'css-loader')

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGanonsideView Question on Stackoverflow
Solution 1 - ReactjsKamil LelonekView Answer on Stackoverflow
Solution 2 - ReactjsvaughanView Answer on Stackoverflow
Solution 3 - ReactjsChrisView Answer on Stackoverflow
Solution 4 - ReactjsGanonsideView Answer on Stackoverflow