webentwicklung-frage-antwort-db.com.de

CSS-Dateien in isomorphen Reaktkomponenten importieren

Ich habe eine React-Anwendung mit in ES6 geschriebenen Komponenten - über Babel und Webpack übertragen.

An einigen Stellen möchte ich bestimmte CSS-Dateien mit bestimmten Komponenten einfügen, wie in reag webpack cookbook vorgeschlagen.

Wenn ich jedoch in einer Komponentendatei ein statisches CSS-Asset benötige, z.

import '../assets/css/style.css';

Dann schlägt die Kompilierung mit einem Fehler fehl:

SyntaxError: <PROJECT>/assets/css/style.css: Unexpected character '#' (3:0)
    at Parser.pp.raise (<PROJECT>\node_modules\babel-core\lib\acorn\src\location.js:73:13)
    at Parser.pp.getTokenFromCode (<PROJECT>\node_modules\babel-core\lib\acorn\src\tokenize.js:423:8)
    at Parser.pp.readToken (<PROJECT>\node_modules\babel-core\lib\acorn\src\tokenize.js:106:15)
    at Parser.<anonymous> (<PROJECT>\node_modules\babel-core\node_modules\acorn-jsx\inject.js:650:22)
    at Parser.readToken (<PROJECT>\node_modules\babel-core\lib\acorn\plugins\flow.js:694:22)
    at Parser.pp.nextToken (<PROJECT>\node_modules\babel-core\lib\acorn\src\tokenize.js:98:71)
    at Object.parse (<PROJECT>\node_modules\babel-core\lib\acorn\src\index.js:105:5)
    at exports.default (<PROJECT>\node_modules\babel-core\lib\babel\helpers\parse.js:47:19)
    at File.parse (<PROJECT>\node_modules\babel-core\lib\babel\transformation\file\index.js:529:46)
    at File.addCode (<PROJECT>\node_modules\babel-core\lib\babel\transformation\file\index.js:611:24)

Wenn ich versuche und benötige eine CSS-Datei in einer Komponentendatei, wird der Babel-Loader dies als eine andere Quelle interpretieren und versuchen, das CSS in Javascript zu übersetzen.

Wird das erwartet? Gibt es einen Weg, um dies zu erreichen: Ermöglichen, dass transpiled Dateien statische Assets explizit referenzieren, die nicht transpiliert werden sollen?

Ich habe Loader für .js/jsx und CSS-Assets wie folgt angegeben:

  module: {
    loaders: [
      { test: /\.css$/, loader: "style-loader!css-loader" },
      { test: /\.(js|jsx)$/, exclude: /node_modules/, loader: 'babel'}
    ]
  }

Die vollständige Webpack-Konfigurationsdatei anzeigen

FULL DETAILS UNTEN:

webpack.common.js - Eine Basis-Webpack-Konfiguration, die ich verwende, damit ich Eigenschaften zwischen dev und production teilen kann.

Gruntfile.js - Für die Entwicklung verwendetes Gruntfile. Wie Sie sehen, ist die Webpack-Konfiguration oben erforderlich und fügt einige Entwicklungseigenschaften hinzu. Könnte dies das Problem verursachen?

Html.jsx - Meine HTML-jsx-Komponente, die versucht, das CSS zu importieren/zu benötigen. Dies ist eine isomorphe App (mit Fluxbile ), daher muss der eigentliche HTML-Code als gerenderte Komponente verwendet werden. Die Verwendung der in dieser Datei in irgendeinem Teil meiner Anwendung enthaltenen Anweisung "request" führt zu dem beschriebenen Fehler. 

Es scheint etwas mit Grunzen zu tun zu haben. Wenn ich nur mit webpack --config webpack.common.js kompiliere, erhalte ich keine Fehler. 

Kurze Antwort: Es handelt sich um einen Laufzeitfehler des Knotens. Es ist keine gute Idee, CSS in isomorphen Apps auf den Server zu laden. 

40
duncanhall

Sie können keine css in der Komponente anfordern, die Sie auf dem Server rendern. Eine Möglichkeit, damit umzugehen, besteht darin, zu prüfen, ob es sich um einen Browser handelt, bevor css benötigt wird.

if (process.env.BROWSER) {
  require("./style.css");
}

Um dies zu ermöglichen, sollten Sie process.env.BROWSER auf false setzen (oder löschen) auf dem Server server.js

delete process.env.BROWSER;
...
// other server stuff

und setzen Sie es für den Browser auf true. Sie machen dies mit dem DefinePlugin von webpack in der config -webpack.config.js.

plugins: [
    ...
    new webpack.DefinePlugin({
        "process.env": {
            BROWSER: JSON.stringify(true)
        }
    })
]

Sie können dies in Aktion in gpbls Isomorphic500 app sehen.

64
Viacheslav

Wenn Sie eine isomorphe App mit ES6 erstellen und CSS beim Rendern auf dem Server einschließen möchten (wichtig, damit grundlegende Stile in der ersten HTTP-Antwort an den Client gesendet werden können), sollten Sie den _7_de_de_de7-Dekorator @withStyles verwenden Reaktiv Starter Kit.

Diese kleine Schönheit hilft sicherzustellen, dass Benutzer Ihre Inhalte mit Styles sehen, wenn die Seite zum ersten Mal gerendert wird. Hier ist eine isomorphe Beispielanwendung Ich baue diese Technik auf. Suchen Sie einfach in der Codebase nach @withStyles, um zu sehen, wie sie verwendet wird. Es geht ein bisschen so:

import React, { Component, PropTypes } from 'react';
import styles from './ScheduleList.css';
import withStyles from '../../decorators/withStyles';

@withStyles(styles)
class ScheduleList extends Component {
8
Josh Habdas
6
asdfasdfads

Wir hatten ein ähnliches Problem mit unserer isomorphen App (und viele andere Probleme finden Sie Details hier ). Was das Problem beim CSS-Import angeht, so haben wir zunächst process.env.BROWSER verwendet. Später haben wir zu babel-plugin-transform-requir-ignore gewechselt. Es funktioniert perfekt mit babel6. 

Sie brauchen nur den folgenden Abschnitt in Ihrer .babelrc zu haben

"env": {
   "node": {
     "plugins": [
       [
         "babel-plugin-transform-require-ignore", { "extensions": [".less", ".css"] }
       ]
     ]
   }
}

Danach starten Sie Ihre App mit BABEL_ENV = 'node'. So wie das:

BABEL_ENV='node' node app.js.

Hier ist ein Beispiel, wie eine Produktions-Konfiguration aussehen kann.

5
koorchik

Ich habe dieses babel plugin mit Erfolg verwendet, um ein ähnliches Problem mit weniger, svg und Bildern zu lösen. Aber es sollte mit allen Nicht-js-Assets funktionieren.

Es schreibt alle Assets in Variablen um. Solange Sie den kompilierten Code nur auf dem Server ausführen und ein Paket mit Webpack für den Client erstellt haben, sollte dies in Ordnung sein.

Der einzige Nachteil ist, dass es nur mit benannten Importen funktioniert. Sie müssen also:

import styles from './styles.css';

damit es funktioniert.

2
Raul Matei

Stellen Sie sicher, dass Sie die Loader in Ihrer Webpack-Konfiguration verwenden: 

  module: {
     loaders: [
        { test: /\.jsx$/, exclude: /node_modules/, loader: "babel" },
        { test: /\.css$/, loader: "style!css" }
     ]
  }
1
gpbl

Möglicherweise liegt in Ihrer Webpack-Konfiguration ein Fehler vor, wenn Sie den babel-loader für alle Dateien verwenden und nicht nur .js-Dateien. Sie möchten einen CSS-Loader für .css-Dateien verwenden.

Sie sollten jedoch nicht import zum Laden eines anderen Moduls als Javascript-Modulen verwenden, da nach dem Importieren in Browsern nur Javascript-Dateien importiert werden können. Verwenden Sie stattdessen require, wenn Sie webpackspezifische Funktionen benötigen.

ORIGINAL POST

Webpack verwendet require und Babel ermöglicht die Verwendung von import von ES6, die meistens dasselbe tun (und Babel übersetzt den Import in eine Requirement-Anweisung). Mit der Funktion require von Webpacks können Sie mehr als nur einen Modulnamen angeben. Außerdem können Sie Loader angeben. Dies ist bei ES6 imports nicht möglich. Wenn Sie also eine CSS-Datei laden möchten, sollten Sie require anstelle von import verwenden.

Der Grund dafür ist, dass Babel nur ein Transpiler für das ist, was in ES6 kommt. Mit ES6 können Sie keine CSS-Dateien importieren. Also lässt Babel das auch nicht zu.

1
Anders Ekdahl

Ich habe endlich erkannt, dass dieser Fehler nicht in der Kompilierphase entsteht, sondern zur Laufzeit. Da es sich um eine ismorphe App handelt, werden die Komponenten und etwaige Abhängigkeiten, die sie haben, zuerst auf dem Server (dh im Knoten) analysiert. Es ist das, was den Fehler verursacht.

Vielen Dank für alle Vorschläge. Ich werde mehr posten, wenn ich herausfinden möchte, wie Stylesheets für einzelne Komponenten in einer isomorphen Anwendung verfügbar sind. 

0
duncanhall

Ich habe auch das gleiche Problem, wenn ich das serverseitige Rendern machen möchte.

Also schreibe ich ein Postcss-Plugin, Postcss-Hash-Klassenname .

Sie benötigen css nicht direkt.

Sie benötigen Ihre CSS-Klassenname-JS-Datei.

Da Sie lediglich eine js-Datei benötigen, können Sie das serverseitige Rendern wie gewohnt durchführen.

Darüber hinaus verwendet dieses Plugin auch Ihren Klassennamen und Dateipfad, um einen eindeutigen Hash zu generieren, um das CSS-Anwendungsproblem zu lösen.

Du kannst es versuchen!

0
Chen-Tai Hou