Импорт файлов CSS в изоморфных компонентах React
У меня есть приложение React с компонентами, написанными на ES6 - переданными через Babel и Webpack.
В некоторых местах я хотел бы включить определенные 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.common.js - базовая конфигурация webpack, которую я использую, чтобы я мог делиться свойствами между dev и production.
Gruntfile.js - Gruntfile используется для разработки. Как вы можете видеть, для этого требуется указанная выше конфигурация веб-пакета и добавлены некоторые свойства разработки. Может ли это быть причиной проблемы?
Html.jsx - мой HTML-компонент jsx, который пытается импортировать / требовать CSS. Это изоморфное приложение (использующее Fluxbile), поэтому необходимо иметь фактический HTML как визуализированный компонент. Использование оператора require, показанного в этом файле в любой части моего приложения, дает описанную ошибку.
Кажется, это как-то связано с ворчанием. Если я просто скомпилирую с webpack --config webpack.common.js
тогда я не получаю ошибок.
Краткий ответ: это ошибка времени выполнения узла. Попытка загрузить CSS на сервер в изоморфных приложениях не очень хорошая идея.
9 ответов
Вы не можете требовать CSS в компоненте, который вы отображаете на сервере. Один из способов справиться с этим - проверить, является ли это браузер, прежде чем требовать CSS.
if (process.env.BROWSER) {
require("./style.css");
}
Чтобы сделать это возможным, вы должны установить process.env.BROWSER
в false
(или удалите его) на сервере server.js
delete process.env.BROWSER;
...
// other server stuff
и установите его true
для браузера. Вы делаете это с помощью DefinePlugin webpack в конфиге - webpack.config.js
plugins: [
...
new webpack.DefinePlugin({
"process.env": {
BROWSER: JSON.stringify(true)
}
})
]
Вы можете увидеть это в действии в приложении gpbl Isomorphic500.
Если вы создаете изоморфное приложение с ES6 и хотите включить CSS при рендеринге на сервере (важно, чтобы основные стили могли быть отправлены клиенту в первом HTTP-ответе), проверьте @withStyles
ES7 декоратор используется в React Starter Kit.
Эта маленькая красота помогает пользователям видеть ваш контент в стилях при первой визуализации страницы. Вот пример изоморфного приложения, которое я создаю, используя эту технику. Просто найдите кодовую базу для @withStyles
чтобы увидеть, как это используется. Это выглядит примерно так:
import React, { Component, PropTypes } from 'react';
import styles from './ScheduleList.css';
import withStyles from '../../decorators/withStyles';
@withStyles(styles)
class ScheduleList extends Component {
У нас была похожая проблема с нашим изоморфным приложением (и много других проблем, вы можете найти подробности здесь). Что касается проблемы с импортом CSS, сначала мы использовали process.env.BROWSER. Позже мы переключились на https://www.npmjs.com/package/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.
Вот пример того, как может выглядеть производственный конфигурационный файл.
Вы также можете попробовать это https://github.com/halt-hammerzeit/webpack-isomorphic-tools
или это https://github.com/halt-hammerzeit/webpack-react-redux-isomorphic-render-example
Я успешно использовал этот плагин babel, чтобы решить похожую проблему с помощью less, svg и images. Но он должен работать с любыми активами не JS.
Он переписывает весь импорт ресурсов в переменные, поэтому, пока вы запускаете скомпилированный код только на сервере и у вас есть пакет, собранный с веб-пакетом для клиента, все должно быть в порядке.
Единственным недостатком является то, что он работает только с именованным импортом, поэтому вам придется:
import styles from './styles.css';
чтобы заставить это работать.
Убедитесь, что вы используете загрузчики в конфигурации вашего веб-пакета:
module: {
loaders: [
{ test: /\.jsx$/, exclude: /node_modules/, loader: "babel" },
{ test: /\.css$/, loader: "style!css" }
]
}
Возможно, у вас есть ошибка в конфигурации Webpack, когда вы используете babel-loader
для всех файлов, а не только .js
файлы. Вы хотите использовать загрузчик CSS для .css
файлы.
Но вы не должны использовать import
для загрузки любого другого модуля, кроме модулей Javascript, поскольку после того, как импорт реализован в браузерах, вы сможете импортировать только файлы Javascript. использование require
вместо этого в случаях, когда вам нужны специальные функции Webpack.
ОРИГИНАЛЬНАЯ ПОЧТА
Webpack использует require
и Бабель позволяет вам использовать import
из ES6, которые в основном делают то же самое (и Babel переносит импорт в оператор require), но они не являются взаимозаменяемыми. Webpacks require
Функция позволяет вам указать не только имя модуля, но и указать загрузчики, что невозможно сделать с ES6. import
s. Так что если вы хотите загрузить файл CSS, вы должны использовать require
вместо import
,
Причина в том, что Babel - это просто переносчик того, что будет в ES6, а ES6 не позволит вам импортировать файлы CSS. Так что Бабель тоже не позволит тебе сделать это.
Я также столкнулся с той же проблемой, когда хочу выполнить рендеринг на стороне сервера.
Поэтому я пишу плагин postcss, https://github.com/ctxhou/postcss-hash-classname.
Вы не требуете CSS прямо.
Вам требуется ваш файл css classname js.
Поскольку все, что вам нужно, это файл js, вы можете выполнить рендеринг на стороне сервера как обычно.
Кроме того, этот плагин также использует ваше имя класса и путь к файлу для генерации уникального хэша для решения проблемы области видимости CSS.
Можешь попробовать!
Решено с этим...
https://github.com/michalkvasnicak/babel-plugin-css-modules-transform
$ npm install --save-dev babel-plugin-css-modules-transform
Включить плагин в.babelrc
{
"plugins": ["css-modules-transform"]
}
И импортируйте Css... как это где угодно
const styles = require('./test.css');
OR
import css from './styles.css'
См. Также это... Помимо файлов Css......................................................... https://www.npmjs.com/package/babel-plugin-transform-assets
Наконец-то я понял, что эта ошибка возникает не на этапе компиляции, а во время выполнения. Поскольку это изоморфное приложение, компоненты и любые их зависимости сначала будут проанализированы на сервере (т. Е. В узле). Это то, что вызывает ошибку.
Спасибо за все предложения, я опубликую больше, если / когда я выясню, как иметь отдельные таблицы стилей в изоморфном приложении.