在同构React组件中导入CSS文件
我有一个用ES6编写的组件的React应用程序 – 通过Babel和Webpack传输。
在一些地方,我想包含特定的CSS文件与特定的组件,如反应webpack食谱build议
但是,如果在任何组件文件中,我需要一个静态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'} ] }
查看完整的webpackconfiguration文件
完整的细节如下:
webpack.common.js – 我使用的基本webpackconfiguration,所以我可以共享开发和生产之间的属性。
Gruntfile.js – 用于开发的Gruntfile。 正如你可以看到它需要上面的webpackconfiguration,并添加一些开发属性。 这是否会导致问题?
Html.jsx – 我试图导入/需要CSS的HTML jsx组件。 这是一个同构的应用程序(使用Fluxbile ),因此需要有实际的HTML作为渲染组件。 使用在这个文件中看到的require语句,在我的应用程序的任何部分给出了所描述的错误。
这似乎与咕噜声有关 。 如果我只是编译与webpack --config webpack.common.js
然后我没有得到任何错误。
简短的回答 :这是一个节点运行时错误。 尝试在同构应用程序中加载服务器上的CSS不是一个好主意。
您不能在您要在服务器上呈现的组件中需要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应用程序中看到这个动作。
如果您使用ES6构build同构应用程序,并希望在服务器上呈现时包含CSS(重要的是,基本样式可以在第一个HTTP响应中发送到客户端),请查看React Starter Kit中使用的@withStyles
ES7修饰符。
这个小小的美景有助于确保用户在页面首次呈现时可以看到您的内容。 这是一个示例同构的应用程序,我正在利用这种技术。 只需在@withStyles
search代码库,看看它是如何使用的。 它有点像这样:
import React, { Component, PropTypes } from 'react'; import styles from './ScheduleList.css'; import withStyles from '../../decorators/withStyles'; @withStyles(styles) class ScheduleList extends Component {
你也可以试试这个https://github.com/halt-hammerzeit/webpack-isomorphic-tools
或者这个https://github.com/halt-hammerzeit/webpack-react-redux-isomorphic-render-example
我用这个babel插件成功解决了一个类似的问题,less了,svg和图像。 但它应该与任何非js资产一起工作。
它会将所有资产导入重写为variables,所以只要在服务器上运行编译后的代码,并为客户机构build一个使用webpack构build的包,应该没问题。
唯一的缺点是它只能使用命名导入,所以你必须:
import styles from './styles.css';
为了使它工作。
我们有一个类似的问题,我们的同构应用程序(和许多其他问题,你可以在这里find细节 )。 至于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.
下面是一个生产configuration如何的例子。
确保你在你的webpackconfiguration中使用加载器:
module: { loaders: [ { test: /\.jsx$/, exclude: /node_modules/, loader: "babel" }, { test: /\.css$/, loader: "style!css" } ] }
你可能在你的Webpackconfiguration中有一个错误,你使用babel-loader
来处理所有文件,而不仅仅是.js
文件。 你想使用一个css加载器.css
文件。
但是,不应该使用import
来加载除Javascript模块之外的任何其他模块,因为一旦导入在浏览器中实现,您将只能导入Javascript文件。 在需要Webpack特定function的情况下使用require
。
原来的post
Webpack使用require
而Babel让你使用从ES6 import
的东西(而Babel将导入转换为require语句),但它们不可互换。 Webpack require
function可以让你指定的不仅仅是一个模块的名字,它还允许你指定加载器,而你不能用ES6 import
。 所以如果你想加载一个CSS文件,你应该使用require
而不是import
。
原因是Babel只是ES6中的一个转换器,而ES6不允许你导入CSS文件。 所以巴别尔也不会让你这样做的。
我终于意识到这个错误不是源于编译阶段,而是源于运行时。 因为这是一个ismorphic应用程序,所以它们的组件和任何依赖关系都将首先在服务器上被parsing(即在节点中)。 这是造成错误的原因。
感谢所有的build议,我会发布更多,如果/当我弄清楚如何在同构应用程序中的每个组件样式表。
当我想要做服务器端渲染时,我也遇到了同样的问题。
所以我写了一个postcss插件postcss-hash-classname 。
你不需要直接的CSS。
你需要你的css classname js文件。
因为所有你需要的是js文件,所以你可以照常进行服务器端渲染。
此外,这个插件也使用你的类名和文件path来生成独特的散列来解决CSS范围问题。
你可以尝试一下!