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

JavaScript Webpack

逆天Davaid

2020-03-24

我有一个用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)

看来,如果我尝试在Component文件中要求CSS文件,那么Babel加载程序会将其解释为另一个来源,并尝试将CS​​S转换为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 - A base webpack config I use, so I can share properties between dev and production.

Gruntfile.js - Gruntfile used for development. As you can see it requires the webpack config above and adds some development properties to it. Could this be causing the problem?

Html.jsx - My HTML jsx component that tries to import/require the CSS. This is an isomorphic app (using Fluxbile), hence needing to have the actual HTML as a rendered component. Using the require statement seen in this file, in any part of my application, gives the error described.

It seems to be something to do with grunt. If I just compile with webpack --config webpack.common.js then I get no errors.

Short answer: It's a node runtime error. Trying to load CSS on the server in isomorphic apps is not a good idea.

第3462篇《在同构React组件中导入CSS文件》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

6个回答
宝儿 2020.03.24

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

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

您不需要直接使用CSS。

您需要CSS类名js文件。

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

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

你可以尝试一下!

Mandy神乐 2020.03.24

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

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

小宇宙 2020.03.24

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

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

您在Webpack配置中可能会对babel-loader所有文件(而不只是.js文件)使用错误。您要对.css文件使用css加载器

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

原始帖子

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

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

神无 2020.03.24

您不需要在服务器上呈现的组件中使用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应用。

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android