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

IT技术 javascript reactjs webpack babeljs
2021-02-21 15:01:03

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

在某些地方,我想包含具有特定组件的特定 CSS 文件,如react webpack 食谱中所建议的

但是,如果在任何组件文件中我需要一个静态 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 不是一个好主意。

6个回答

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

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

为了使人们有可能,你应该设置process.env.BROWSERfalse(或删除)在服务器 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应用。

我相信有一种方法可以在服务器端导入 css 等,但需要使用单独的配置将服务器端代码与 Webpack 捆绑到用于客户端的 bundle.js 我不喜欢使用装饰器的选项和我也不喜欢在最终用户禁用 Javascript 的情况下只能在客户端要求非 JS module的想法。我目前正在研究 Webpack 服务器端的细节
2021-05-01 15:01:03
我想我遇到了同样的问题,但不得不用这样的条件逻辑包装 .css 导入似乎真的很难看。还有其他解决方案吗?@snegostup
2021-05-04 15:01:03
stackoverflow.com/questions/60473782/…请也回答这个问题,或者对这个查询的任何见解表示赞赏。
2021-05-10 15:01:03
一百万次是的!谢谢你。
2021-05-18 15:01:03

如果您正在使用 ES6 构建同构应用程序,并希望在服务器上渲染时包含 CSS(很重要,因此可以在第一个 HTTP 响应中将基本样式发送到客户端),请查看@withStylesReact Starter Kit 中使用ES7 装饰器。

这种小小的美感有助于确保用户在首次呈现页面时看到具有样式的内容这是我利用这种技术构建的同构应用程序示例只需搜索代码库@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。后来我们切换到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.

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

或者你可以在你为服务器加载的 'babel-register's 选项中启用它(不要弄乱环境变量): require("babel-register")({ plugins: [ [ "transform-require-ignore", {"扩展名": [".css"]} ] ] })
2021-05-15 15:01:03
惊讶这个答案没有更多的赞成票,似乎 webpack-isomorphic-tools 是理想的解决方案
2021-05-09 15:01:03

成功地使用了这个babel 插件来解决一个类似的问题,包括 less、svg 和图像。但它应该适用于任何非 js 资产。

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

唯一的缺点是它只适用于命名导入,因此您必须:

import styles from './styles.css';

以使其工作。