okno nie zdefiniowano błędu podczas korzystania z extract-text-webpack-plugin React

83

Używam pakietu webpack do budowania moich komponentów reagowania i próbuję użyć extract-text-webpack-plugindo oddzielenia mojego css od mojego wygenerowanego pliku js. Jednak, gdy próbuję zbudować komponentu pojawia się następujący błąd: Module build failed: ReferenceError: window is not defined.

Mój plik webpack.config.js wygląda następująco:

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
źródło
5
znalazłem odpowiedź. zamiast ExtractTextPlugin.extract('style-loader!css-loader')pisaćExtractTextPlugin.extract('style-loader', 'css-loader')
Ganonside
3
Czy możesz zamienić to na odpowiedź i oznaczyć problem jako rozwiązany? Dzięki.
Juho Vepsäläinen
Właśnie zrobiłem. Przepraszam za to.
Ganonside

Odpowiedzi:

60

Możesz użyć style-loaderjako beforeargumentu w extractfunkcji.

Oto natywna implementacja:

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

Więc w zasadzie to, co musisz zrobić, to:

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

jeśli na przykład używasz sass.

Kamil Lelonek
źródło
To rozwiązało również problem podczas pracy z Stylusem. Dzięki @squixy!
Gabriel Godoy
1
Jeśli masz problem z scss not sass, usuń wcięcieSyntax = true
Robert Leggett
43

Nie widziałem wyjaśnienia przyczyny, więc zamieściłem tę odpowiedź tutaj.

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

ExtractTextPlugin.extract([notExtractLoader], loader, [options]) Tworzy program ładujący wyodrębniający z istniejącego programu ładującego.

notExtractLoader (opcjonalnie) programy ładujące, które powinny być używane, gdy css nie jest wyodrębniany (tj. w dodatkowej porcji, gdy allChunks: false)

loader moduł (i) ładujące, które powinny być użyte do konwersji zasobu do modułu eksportującego css.

options

publicPath zastępuje ustawienie publicPath dla tego programu ładującego.

#extractSposób powinien otrzymać Loader wyjścia css. To, co się działo, polegało na tym, że otrzymywał plik, style-loaderktóry generuje kod javascript , który ma zostać wstrzyknięty na stronę internetową. Ten kod będzie próbował uzyskać dostęp window.

Nie należy przekazywać ciągu ładującego z styledo #extract. Jednak ... jeśli ustawisz allChunks=false, nie będzie budować plików CSS dla fragmentów innych niż początkowe. Dlatego musi wiedzieć, jakiego modułu ładującego użyć, aby wstrzyknąć na stronę.

Wskazówka: Webpack to narzędzie, które naprawdę wymaga dogłębnego zrozumienia, w przeciwnym razie możesz napotkać wiele dziwnych problemów.

vaughan
źródło
Najlepsze rzeczy, jakie kiedykolwiek słyszałem o webpacku.
Jide
przepraszam, że nie mam wyjaśnienia w mojej odpowiedzi. Dokumentacja pakietu internetowego była nadal pisana (i może nadal być) w czasie, gdy opublikowałem pytanie i odpowiedź. Ale zgadzam się, że trzeba to całkiem dobrze zrozumieć.
Ganonside
1
Wysokiej jakości treści tutaj. Gdyby dokumentacja była w połowie tak dobra, byłbym naprawdę szczęśliwym programistą.
Rocío García Luque
20

Pakiet internetowy 2

Jeśli używasz Webpack 2, ta odmiana działa:

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

Nowa metoda wyodrębniania nie przyjmuje już trzech argumentów i jest wyświetlana jako istotna zmiana podczas przechodzenia z wersji V1 do V2.

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

Chris
źródło
12

Znalazłem rozwiązanie mojego problemu:

Zamiast podłączać moduły ExtractTextPlugin.extract('style-loader!css-loader')ładujące do siebie nawzajem ( ), musisz przekazać każdy moduł ładujący jako oddzielny parametr:ExtractTextWebpackPlugin.extract('style-loader', 'css-loader')

Ganonside
źródło
8
Jestem całkiem pewien, że to właśnie powiedział @squixy 5 miesięcy wcześniej.
cchamberlain
3
Stwierdzenie „każdy program ładujący jako oddzielny parametr” jest prawdziwe tylko dla dwóch programów ładujących i jest błędne dla trzech lub więcej. extractFunkcja przyjmuje trzy parametry: (before, loader, options)i ta odpowiedź pokryw, które doskonale: stackoverflow.com/a/30982133/1346510
sompylasar
1
@sompylasar bardzo dziękuję za ten komentarz. To rozwiązało mój problem! Założyłem, że wszystkie przekazane parametry będą po prostu przepuszczane. Z radością 'style', 'css', 'sass'mogę powiedzieć, że jeśli potrzebujesz , możesz po prostu zmienić to na 'style', 'css!sass'- Dzięki!
Aleski
3
TO NIEPRAWIDŁOWE przeczytaj powyższe komentarze lub odpowiedz. Pogrubioną czcionką, ponieważ ktoś przeczyta tę odpowiedź i nie zrozumie, dlaczego ExtractTextPlugin nie używa wszystkich swoich programów ładujących.
Don P
Inne odpowiedzi wydają się działać dla innych, ale kiedy opublikowałem pytanie, to właśnie zadziałało, więc zaznaczyłem je.
Ganonside,