javascript-在同构React组件中导入CSS文件

我有一个带有ES6编写的组件的React应用程序-通过Babel和Webpack进行了编译。

在某些地方,我想包含特定CSS文件和特定组件,如react webpack手册中所建议

但是,如果在任何组件文件中,我都需要静态CSS资产,例如:

webpack --config webpack.common.js

然后编译失败并显示错误:

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)

看来,如果我尝试在Component文件中要求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-我的HTML jsx组件,尝试导入/获取CSS。 这是一个同构应用程序(使用Fluxbile),因此需要使用实际的HTML作为呈现的组件。 在我的应用程序的任何部分中,使用此文件中显示的require语句,都会给出所描述的错误。

这似乎与咕unt有关。 如果我仅使用webpack --config webpack.common.js进行编译,则不会出错。

简短的答案:这是节点运行时错误。 在同构应用程序中尝试在服务器上加载CSS并不是一个好主意。

duncanhall asked 2020-08-10T23:22:52Z
9个解决方案
66 votes

您不需要在服务器上呈现的组件中使用CSS。 处理它的一种方法是在需要CSS之前检查它是否是浏览器。

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

为了使它成为可能,您应该在服务器上将true设置为false(或将其删除)server.js

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

并将其设置为浏览器的true。 您可以在配置中使用webpack的DefinePlugin-webpack.config.js

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

您可以在gpbl的Isomorphic500应用程序中看到此操作。

Viacheslav answered 2020-08-10T23:23:11Z
9 votes

如果您要使用ES6构建同构应用程序,并希望在服务器上进行渲染时包括CSS(重要的一点,以便可以在第一个HTTP响应中将基本样式发送给客户端),请查看React Starter Kit中使用的@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 {
Josh Habdas answered 2020-08-10T23:23:36Z
6 votes

您也可以尝试[https://github.com/halt-hammerzeit/webpack-isomorphic-tools]

或这个[https://github.com/halt-hammerzeit/webpack-react-redux-isomorphic-render-example]

asdfasdfads answered 2020-08-10T23:24:00Z
6 votes

同构应用程序也遇到了类似的问题(还有很多其他问题,您可以在此处找到详细信息)。 至于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.

这是生产配置的外观示例。

koorchik answered 2020-08-10T23:24:33Z
2 votes

我成功使用了这个babel插件,用更少的svg和图像解决了类似的问题。 但它应与任何非js资产一起使用。

它将所有资产导入重写为变量,因此,只要您仅在服务器上运行已编译的代码,并为客户端提供一个用webpack生成的捆绑包,就可以了。

唯一的缺点是它只能与命名的导入一起使用,因此您必须:

import styles from './styles.css';

为了使它工作。

Raul Matei answered 2020-08-10T23:25:06Z
1 votes

确保在webpack配置中使用加载程序:

  module: {
     loaders: [
        { test: /\.jsx$/, exclude: /node_modules/, loader: "babel" },
        { test: /\.css$/, loader: "style!css" }
     ]
  }
gpbl answered 2020-08-10T23:25:26Z
1 votes

您的Webpack配置中可能有一个错误,其中您对所有文件而不只是import文件使用require。 您要对require文件使用CSS加载程序。

但您不应使用require加载Javascript模块以外的任何其他模块,因为一旦在浏览器中实现了导入,您将只能导入Javascript文件。 如果需要Webpack特定功能,请改用import

原始帖子

Webpack使用require,而Babel允许您使用ES6中的import,它们大多做相同的事情(Babel将导入转换为require语句),但它们不可互换。 Webpacks require函数不仅可以指定模块名称,还可以指定装载程序,而ES6 imports则不能。 因此,如果要加载CSS文件,则应使用require而不是import

原因是Babel只是ES6中即将推出的东西的编译器,而ES6将不允许您导入CSS文件。 因此,Babel也不允许您这样做。

Anders Ekdahl answered 2020-08-10T23:26:05Z
0 votes

我终于意识到,该错误不是起源于编译阶段,而是起源于运行时。 由于这是一个变形应用程序,因此首先将在服务器上(即,在节点中)解析组件及其所具有的任何依赖关系。 这是导致错误的原因。

感谢所有建议,如果/当我想出如何在同构应用程序中使用每个组件的样式表时,我将发布更多内容。

duncanhall answered 2020-08-10T23:26:29Z
0 votes

当我要执行服务器端渲染时,我也遇到了同样的问题。

所以我写了一个postcss插件postcss-hash-classname。

您不需要直接使用CSS。

您需要CSS类名js文件。

由于您只需要js文件,因此您可以照常进行服务器端渲染。

此外,此插件还使用您的类名和文件路径生成唯一的哈希值,以解决css范围问题。

你可以试试!

Chen-Tai Hou answered 2020-08-10T23:27:15Z
translate from https://stackoverflow.com:/questions/30347722/importing-css-files-in-isomorphic-react-components