Подтвердить что ты не робот

Импорт файлов CSS в изоморфных компонентах React

У меня есть приложение React с компонентами, написанными на ES6, - переданные через Babel и Webpack.

В некоторых местах я хотел бы включить определенные файлы CSS с конкретными Компонентами, как предложено в ответить на веб-кухню cookbook

Однако, если в любом файле Component мне нужен статический ресурс 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 в файле Component, тогда загрузчик 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, которую я использую, поэтому я могу делиться свойствами между dev и production.

Gruntfile.js - Gruntfile, используемый для разработки. Как вы видите, для этого требуется конфигурация webpack выше и добавляет к ней некоторые свойства разработки. Может ли это вызвать проблему?

Html.jsx - Мой компонент HTML jsx, который пытается импортировать/требовать CSS. Это изоморфное приложение (с использованием Fluxbile), поэтому необходимо иметь фактический HTML как обработанный компонент. Используя инструкцию require, увиденную в этом файле, в любой части моего приложения выдает описанную ошибку.

Кажется, что-то связано с хрюканьем. Если я просто скомпилирован с webpack --config webpack.common.js, то я не получу ошибок.

Короткий ответ. Это ошибка node. Попытка загрузить CSS на сервере в изоморфных приложениях не является хорошей идеей.

4b9b3361

Ответ 1

Вы не можете требовать css в компоненте, который вы рендерите на сервере. Один из способов борьбы с ним - проверить, не является ли это браузером перед запросом css.

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

Чтобы сделать возможным, вы должны установить process.env.BROWSER в false (или удалить его) на сервере server.js

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

и установите для него true для браузера. Вы делаете это с помощью webpack DefinePlugin в config - webpack.config.js

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

Это можно увидеть в действии в приложении gpbl Isomorphic500.

Ответ 2

Если вы создаете изоморфное приложение с ES6 и хотите включать CSS при рендеринге на сервере (важно, чтобы базовые стили могли быть отправлены клиенту в первом ответе HTTP), проверьте @withStyles Декоратор ES7, используемый в наборе реагентов для начинающих.

Эта небольшая красавица помогает пользователям видеть ваш контент со стилями, когда страница сначала отображается. Здесь пример изоморфного приложения Я строю, используя эту технику. Просто найдите код для @withStyles, чтобы узнать, как он используется. Это выглядит примерно так:

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

@withStyles(styles)
class ScheduleList extends Component {

Ответ 4

Я использовал этот плагин babel с успехом, чтобы решить подобную проблему с меньшими, svg и изображениями. Но он должен работать с любыми активами не js.

Он переписывает весь импорт активов в переменные, поэтому, пока вы запускаете скомпилированный код только на сервере и имеете пакет, созданный с помощью webpack для клиента, все должно быть хорошо.

Единственный недостаток заключается в том, что он работает только с имёнными импортами, поэтому вам придется:

import styles from './styles.css';

чтобы заставить его работать.

Ответ 5

У нас была аналогичная проблема с нашим изоморфным приложением (и многие другие проблемы, вы можете найти подробности здесь). Что касается проблемы с импортом 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

Вероятно, у вас есть ошибка в вашей конфигурации Webpack, где вы используете babel-loader для всех файлов, а не только файлы .js. Вы хотите использовать загрузчик css для файлов .css.

Но вы не должны использовать import для загрузки любого другого модуля, кроме модулей Javascript, поскольку после импорта в браузерах вы сможете импортировать только файлы Javascript. Используйте require вместо этого в тех случаях, когда вам нужны специальные функции Webpack.

ОРИГИНАЛЬНАЯ ПОЧТА

Webpack использует require, и Babel позволяет использовать import из ES6, которые в основном делают то же самое (и Babel переводит импорт в инструкцию require), но они не взаимозаменяемы. Функция Webpacks require позволяет указать больше, чем просто имя модуля, оно также позволяет указать загрузчики, что вы не можете сделать с ES6 import s. Поэтому, если вы хотите загрузить файл CSS, вы должны использовать require вместо import.

Причина в том, что Babel является просто транспилером для того, что входит в ES6, и ES6 не позволит вам импортировать файлы CSS. Так что Вавилон не позволит вам это сделать.

Ответ 7

Убедитесь, что вы используете загрузчики в своей конфигурации webpack:

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

Ответ 8

Я наконец понял, что эта ошибка не возникает на этапе компиляции, а скорее во время выполнения. Поскольку это изоморфное приложение, компоненты и любые связанные с ними зависимости сначала анализируются на сервере (т.е. В node). Именно это вызывает ошибку.

Спасибо за все предложения, я опубликую больше, если/когда я выясню, как иметь таблицы стилей для каждого компонента в изоморфном приложении.

Ответ 9

Я также встретил ту же проблему, когда хочу сделать рендеринг на стороне сервера.

Итак, я пишу плагин postcss, postcss-hash-classname.

Вы не требуете css напрямую.

Вам нужен файл css classname js.

Поскольку все, что вам нужно, это js файл, вы можете сделать рендеринг на стороне сервера как обычно.

Кроме того, этот плагин также использует ваше имя класса и путь к файлу для генерации уникального хэша для решения проблемы с областью css.

Вы можете попробовать!