web-dev-qa-db-ja.com

同形のCSSファイルのインポートReactコンポーネント

React ES6で記述されたコンポーネントを備えたアプリケーション-BabelとWebpackを介して変換されたアプリケーションがあります。

react webpack cookbook で提案されているように、特定のコンポーネントに特定のCSSファイルを含めたい場合もあります。

ただし、コンポーネントファイルで静的CSSアセットが必要な場合、たとえば:

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

その後、コンパイルはエラーで失敗します:

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)

コンポーネントファイルでCSSファイルを試して必要とすると、Babelローダーはそれを別のソースとして解釈し、CSSをJavascriptに変換しようとします。

これは予想されますか?これを達成する方法はありますか?-コンパイルされたファイルが、コンパイルされない静的アセットを明示的に参照できるようにしますか

.js/jsxとCSSアセットの両方のローダーを次のように指定しました。

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

完全なwebpack構成ファイル を表示します

以下の詳細:

webpack.common.js -私が使用するベースwebpack構成。そのため、開発者と本番の間でプロパティを共有できます。

Gruntfile.js -開発に使用されるGruntfile。ご覧のとおり、上記のwebpack構成が必要であり、いくつかの開発プロパティが追加されています。これが問題を引き起こしている可能性がありますか?

Html.jsx -CSSのインポート/要求を試みるHTML jsxコンポーネント。これは同形アプリです( Fluxbile を使用)。したがって、レンダリングされたコンポーネントとして実際のHTMLが必要です。アプリケーションの任意の部分で、このファイルにあるrequireステートメントを使用すると、説明されているエラーが発生します。

それはgruntと関係があるようです。 webpack --config webpack.common.jsでコンパイルした場合、エラーは発生しません。

短い答え:ノードランタイムエラーです。同形アプリでサーバーにCSSをロードすることはお勧めできません。

42
duncanhall

サーバーでレンダリングするコンポーネントにcssを要求することはできません。それに対処する1つの方法は、CSSを要求する前にブラウザかどうかを確認することです。

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

それを可能にするには、process.env.BROWSERからサーバー上のfalse(または削除)server.js

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

ブラウザのtrueに設定します。あなたはconfigでwebpackのDefinePluginでそれを行います-webpack.config.js

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

これは、gpblの Isomorphic5 appで実際に見ることができます。

66
Viacheslav

ES6で同形アプリを作成していて、サーバーでのレンダリング時にCSSを含める場合(最初のHTTP応答で基本スタイルをクライアントに送信できるようにするため)、 @withStyles Reactスターターキットで使用されるES7デコレータ。

この小さな美しさは、ページが最初にレンダリングされるときに、ユーザーがコンテンツを確実に表示できるようにしますwith styles同形アプリの例 このテクニックを活用して構築しています。コードベースで@withStylesを検索して、使用方法を確認してください。これは次のようなものです。

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

@withStyles(styles)
class ScheduleList extends Component {
9
Josh Habdas

同形アプリでも同様の問題が発生しました(他の多くの問題もあります 詳細はこちら )。 CSSインポートの問題に関しては、最初はprocess.env.BROWSERを使用していました。後で babel-plugin-transform-require-ignore に切り替えました。 babel6で完全に機能します。

必要なのは、.babelrcに次のセクションがあることです

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

その後、BABEL_ENV = 'node'を指定してアプリを実行します。そのように:

BABEL_ENV='node' node app.js.

ここにあります プロダクション設定がどのように見えるかの例。

6
koorchik
6
asdfasdfads

私はこれを使用しました babel plugin less、svg、imagesで同様の問題を解決しました。ただし、非jsアセットで動作するはずです。

すべてのアセットのインポートを変数に書き換えるため、コンパイルされたコードをサーバー上で実行し、クライアント用にwebpackでビルドされたバンドルがあれば問題ありません。

唯一の欠点は、名前付きインポートでのみ機能することです。そのため、次のことを行う必要があります。

import styles from './styles.css';

それを機能させるために。

2
Raul Matei

Webpack構成でローダーを使用していることを確認してください。

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

おそらく_babel-loader_ファイルだけでなく、すべてのファイルに_.js_を使用しているWebpack構成にエラーがあります。 _.css_ファイルにcssローダーを使用します。

ただし、ブラウザにインポートが実装されると、Javascriptファイルしかインポートできないため、importをJavascriptモジュール以外のモジュールのロードに使用しないでください。 Webpack固有の機能が必要な場合は、代わりにrequireを使用してください。

オリジナルポスト

Webpackはrequireを使用し、BabelではES6のimportを使用できますが、これらはほとんど同じことを行います(そしてBabelはimportをrequireステートメントに変換します)が、互換性はありません。 Webpacks require関数を使用すると、モジュール名だけでなく、ローダーも指定できます。ES6importsではできません。したがって、CSSファイルをロードする場合は、requireの代わりにimportを使用する必要があります。

その理由は、BabelはES6で提供される機能の単なるトランスパイラーであり、ES6ではCSSファイルをインポートできないためです。だから、バベルもあなたにそれを許さないだろう。

1
Anders Ekdahl

私はついに、このエラーはコンパイル段階ではなく、実行時に発生していることに気付きました。これは同形アプリであるため、コンポーネントとそれらが持つ依存関係は、最初にサーバー(つまりノード)で解析されます。これがエラーの原因です。

すべての提案に感謝します。同形アプリケーションでコンポーネントごとのスタイルシートを作成する方法を見つけた場合は、さらに投稿します。

0
duncanhall

サーバー側のレンダリングを実行したいときにも同じ問題に遭遇しました。

そこで、postcssプラグイン postcss-hash-classname を作成します。

Cssを直接必要としません。

Css classname jsファイルが必要です。

必要なのはjsファイルだけなので、通常どおりサーバー側のレンダリングを実行できます。

また、このプラグインはクラス名とファイルパスを使用して一意のハッシュを生成し、CSSスコープの問題を解決します。

あなたはそれを試すことができます!

0
Chen-Tai Hou