Error de ventana no definida al usar extract-text-webpack-plugin React

82

Estoy usando webpack para construir mis componentes de reacción y estoy tratando de usar extract-text-webpack-pluginpara separar mi css de mi archivo js generado. Sin embargo, cuando se intenta generar el componente me sale el siguiente error: Module build failed: ReferenceError: window is not defined.

Mi archivo webpack.config.js se ve así:

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')
  ]
}
Ganonside
fuente
5
Descubrí la respuesta. en lugar de ExtractTextPlugin.extract('style-loader!css-loader')tener que escribirExtractTextPlugin.extract('style-loader', 'css-loader')
Ganonside
3
¿Puedes convertir eso en una respuesta y marcar el problema resuelto? Gracias.
Juho Vepsäläinen
Lo acabo de hacer. Lo siento por eso.
Ganonside

Respuestas:

59

Es posible que desee utilizarlo style-loadercomo beforeargumento en extractfunción.

Aquí está la implementación nativa:

    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("!");
        }
    };

Entonces, básicamente, lo que debes hacer es:

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

si por ejemplo usa sass.

Kamil Lelonek
fuente
Esto también me resolvió al trabajar con Stylus. ¡Gracias @squixy!
Gabriel Godoy
1
Si tiene problemas con scss no sass, elimine el sangradoSyntax = true
Robert Leggett
43

No vi una explicación de la causa, así que publiqué esta respuesta aquí.

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

ExtractTextPlugin.extract([notExtractLoader], loader, [options]) Crea un cargador de extracción de un cargador existente.

notExtractLoader (opcional) el cargador (s) que se deben usar cuando no se extrae el CSS (es decir, en un fragmento adicional> cuando allChunks: falso)

loader los cargadores que se deben usar para convertir el recurso en un módulo de exportación css.

options

publicPath anule la configuración de publicPath para este cargador.

El #extractmétodo debe recibir un cargador que genere css. Lo que estaba sucediendo era que estaba recibiendo un código destyle-loader salida JavaScript , que está destinado a ser inyectado en una página web. Este código intentaría acceder window.

No debe pasar una cadena de cargador con styleto #extract. Sin embargo ... si lo configura allChunks=false, no generará archivos CSS para fragmentos no iniciales. Por lo tanto, necesita saber qué cargador usar para inyectar en la página.

Consejo: Webpack es una herramienta que realmente necesita entenderse en profundidad o puede encontrarse con muchos problemas extraños.

vaughan
fuente
Las mejores cosas que he escuchado sobre webpack.
Jide
perdón por no tener una explicación en mi respuesta. Los documentos del paquete web todavía se estaban escribiendo (y es posible que todavía lo estén) en el momento en que publiqué la pregunta y la respuesta. Pero estoy de acuerdo en que debe entenderse bastante bien.
Ganonside
1
Contenido de alta calidad aquí. Si los documentos fueran la mitad de buenos que esto, sería un programador realmente feliz.
Rocío García Luque
20

Webpack 2

Si está utilizando Webpack 2, esta variación funciona:

    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',
            }],
        }),
    }]

El nuevo método de extracción ya no toma tres argumentos y se muestra como un cambio importante al pasar de V1 a V2.

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

Chris
fuente
12

Descubrí la solución a mi problema:

En lugar de conectar los cargadores entre sí ( ExtractTextPlugin.extract('style-loader!css-loader')), debe pasar cada cargador como un parámetro separado:ExtractTextWebpackPlugin.extract('style-loader', 'css-loader')

Ganonside
fuente
8
Estoy bastante seguro de que esto es lo que @squixy dijo que hiciera 5 meses antes.
cchamberlain
3
La afirmación "cada cargador como un parámetro independiente" es verdadera solo para dos cargadores y es incorrecta para tres o más. La extractfunción toma tres parámetros : (before, loader, options), y esta respuesta lo cubre perfectamente: stackoverflow.com/a/30982133/1346510
sompylasar
1
@sompylasar muchas gracias por este comentario. ¡Ha resuelto mi problema! Asumí que todos los parámetros pasados ​​serían simplemente un bucle directo. Me complace decir que si necesita usarlo 'style', 'css', 'sass', puede cambiarlo a 'style', 'css!sass'- ¡Gracias!
Aleski
3
ESTO ES INCORRECTO lea los comentarios o la respuesta anteriores. Poner esto en negrita porque alguien leerá esta respuesta y no entenderá por qué ExtractTextPlugin no está usando todos sus cargadores.
Don P
Otras respuestas parecen funcionar para otros, pero cuando publiqué la pregunta, esto es lo que funcionó para mí, así que lo marqué.
Ganonside