首页 文章

在Isomorphic React组件中导入CSS文件

提问于
浏览
39

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

在某些地方,我想包含特定组件的特定CSS文件,如react webpack cookbook中所述

但是,如果在任何组件文件中我需要静态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'}
    ]
  }

查看full webpack config file

FULL DETAILS BELOW:

webpack.common.js - 我使用的基本webpack配置,因此我可以在开发和 生产环境 之间共享属性 .

Gruntfile.js - 用于开发的Gruntfile . 正如您所看到的,它需要上面的webpack配置并为其添加一些开发属性 . 这会导致问题吗?

Html.jsx - 我的HTML jsx组件试图导入/需要CSS . 这是一个同构应用程序(使用Fluxbile),因此需要将实际的HTML作为呈现的组件 . 使用此文件中的require语句,在我的应用程序的任何部分中,都会给出所描述的错误 .

It seems to be something to do with grunt . 如果我只是用 webpack --config webpack.common.js 编译,那么我没有错误 .

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

9 回答

  • 1

    我终于意识到这个错误不是源于编译阶段,而是源于运行时 . 因为这是一个异形应用程序,所以它们具有的组件和任何依赖项将首先在服务器上解析(即在节点中) . 正是这导致了错误 .

    谢谢对于所有建议,如果/当我弄清楚如何在同构应用程序中使用每个组件样式表时,我将发布更多内容 .

  • 5

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

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

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

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

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

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

    你可以在gpbl的Isomorphic500 app中看到这个 .

  • 64

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

    这个小小的美丽有助于确保用户在首次呈现页面时使用样式查看您的内容 . 这是example isomorphic app我正在利用这种技术建造 . 只需在代码库中搜索 @withStyles 即可查看它是如何使用的 . 它有点像这样:

    import React, { Component, PropTypes } from 'react';
    import styles from './ScheduleList.css';
    import withStyles from '../../decorators/withStyles';
    
    @withStyles(styles)
    class ScheduleList extends Component {
    
  • 0

    我们的同构应用程序遇到了类似的问题(还有很多其他问题,你可以找到details here) . 至于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.
    

    Here is 生产环境 配置的外观示例 .

  • 0

    我用babel plugin成功地用less,svg和images来解决类似的问题 . 但它应该适用于任何非js资产 .

    它将所有资产导入重写为变量,因此只要您在服务器上运行已编译的代码并使用webpack为客户端构建一个包,就应该没问题 .

    唯一的缺点是它只能使用命名导入,所以你必须:

    import styles from './styles.css';
    

    为了使它工作 .

  • 1

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

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

    你的Webpack配置中可能有一个错误,你正在使用 babel-loader 表示所有文件,而不仅仅是 .js 文件 . 您想为 .css 文件使用css加载程序 .

    但是你不应该使用 import 来加载除Javascript模块之外的任何其他模块,因为一旦在浏览器中实现导入,你将只能导入Javascript文件 . 在需要Webpack特定功能的情况下,请使用 require .

    ORIGINAL POST

    Webpack使用 require ,而Babel允许你使用ES6中的 import ,它们主要做同样的事情(并且Babel将导入转换为require语句),但它们不可互换 . Webpacks require 功能允许您指定的不仅仅是模块名称,它还允许您指定加载器,而不能使用ES6 import . 因此,如果要加载CSS文件,则应使用 require 而不是 import .

    原因是Babel只是ES6中的内容的转换器,而ES6将不允许您导入CSS文件 . 所以巴贝尔也不允许你这样做 .

  • 6

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

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

    您不需要直接使用CSS .

    你需要你的css classname js文件 .

    因为您需要的只是js文件,所以您可以像往常一样进行服务器端渲染 .

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

    你可以尝试一下!

相关问题