【问题标题】:Use CSS Modules in React components with Typescript built by webpack通过 webpack 构建的 Typescript 在 React 组件中使用 CSS 模块
【发布时间】:2016-05-03 00:48:01
【问题描述】:

我想在一个用 Typescript 编写的 React 应用程序中使用带有 webpack 'modules' 选项的 css-loader。 This example 是我的出发点(他们使用 Babel、webpack 和 React)。

webpack 配置

var webpack=require('webpack');
var path=require('path');
var ExtractTextPlugin=require("extract-text-webpack-plugin");

module.exports={
    entry: ['./src/main.tsx'],
    output: {
        path: path.resolve(__dirname, "target"),
        publicPath: "/assets/",
        filename: 'bundle.js'
    },
    debug: true,
    devtool: 'eval-source-map',
    plugins: [
        new webpack.optimize.DedupePlugin(),
        new webpack.optimize.UglifyJsPlugin({minimize: true})
    ],
    resolve: {
        extensions: ['', '.jsx', '.ts', '.js', '.tsx', '.css', '.less']
    },
    module: {
        loaders: [
            {
                test: /\.ts$/,
                loader: 'ts-loader'
            },
            {
                test: /\.tsx$/,
                loader: 'react-hot!ts-loader'
            }, {
                test: /\.jsx$/,
                exclude: /(node_modules|bower_components)/,
                loader: "react-hot!babel-loader"
            },
            {
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                loader: "babel-loader"
            }, {
                test: /\.css/,
                exclude: /(node_modules|bower_components)/,
                loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader')
            }
        ]
    },
    plugins: [
        new ExtractTextPlugin("styles.css", {allChunks: true})
    ],
    postcss: function() {
        return [require("postcss-cssnext")()]
    }
}

这是一个 React 组件,我想用随附的 CSS 文件设置样式:

import React = require('react');
import styles = require('../../../css/tree.css')

class Tree extends React.Component<{}, TreeState> {
...

    render() {
        var components = this.state.components
        return (
            <div>
                <h3 className={styles.h3} >Components</h3>
                <div id="tree" className="list-group">
                    ...
                </div>
            </div>
        )
    }
}

    export = Tree

tree.css

.h3{
    color: red;
}

无论我在做什么(尝试更改导入语法,尝试为 ts-loader 声明“要求”,描述为 here,我总是得到:

未捕获的错误:找不到模块“../../../css/tree.css”

在运行时和

错误 TS2307:找不到模块“../../../css/tree.css”。

由 TS 编译器。发生了什么?在我看来,css-loader 甚至没有发出 ICSS?还是 ts-loader 的行为不对?

【问题讨论】:

  • import someName = require('/some/path') 是两种不同的无效 ;-) - 您使用的是 import 还是 require?
  • 什么意思?那是有效的打字稿语法。 @SeanVieira
  • 是的,TypeScript 采用了自己的模块语法,而 ES6 模块仍在开发中。它是 CJS 和 ES6 之间的混合体,您可以使用 import(如 ES6)但也使用 require(如 CJS)。 TypeScript 也(现在)支持完整的 ES6 语法。

标签: javascript reactjs typescript webpack react-css-modules


【解决方案1】:

import 对 TypeScript 有特殊的意义。这意味着 TypeScript 将尝试加载和理解正在导入的内容。正确的方法是像你提到的那样定义require,然后定义var而不是import:

var styles = require('../../../css/tree.css')`

【讨论】:

  • 我还需要在 d.ts 中定义 'require' 吗?我必须在我的 tsconfig 中以 ES6 为目标吗?我得到了同样的错误@James Brantly
  • 你需要在d.ts中定义require,是的,否则TypeScript会报错没有require函数。目标无关紧要,使用任何目标都应该一样。你还看到具体的“TS2307”吗?如果不是,那么它不再是 TypeScript 错误,而是 webpack 说它找不到文件(由于路径错误)。
  • 是的,你是对的,TS2307 不见了。运行时错误来自 webpack。我需要如何理解路径?是相对于 webpack.config.js 的吗?
  • 不,它与执行要求的文件有关。
  • 对... webpack 就是找不到文件。我尝试将它拉到与 .tsx 文件相同的目录中。不走运...你手头有 Typescript+rect+modules 的工作示例吗?
【解决方案2】:
  1. 根据ts-loader documentation 声明“需要”。
  2. 使用 类型的“require”作为泛型:require("../../../css/tree.css").

*.d.ts 文件

declare var require: {
   <T>(path: string): T;
   (paths: string[], callback: (...modules: any[]) => void): void;
   ensure: (paths: string[], callback: (require: <T>(path: string) => T) => void) => void;
}; 

*.tsx 包含组件的文件

const styles = require<any>("../../../css/tree.css");
...
<h3 className={styles.h3}>Components</h3>

我知道它已经被回答了,但是在我意识到我需要使用泛型类型规范之前,我一直在苦苦挣扎,否则我无法访问 CSS 文件的内容。 (我收到错误:类型“{}”上不存在属性“h3”。)

【讨论】:

  • 是的,或者你可以在 'require' 的声明中去掉通用的 : declare var require:{(path: string): T}
【解决方案3】:

我有类似的问题。 对我来说,作品导入:

import '../../../css/tree.css';

Webpack 像任何其他正常导入一样更改它。将其更改为

__webpack_require__(id)

一个缺点是您失去了对样式变量的控制。

【讨论】:

  • 但是我需要变量 'styles' 来设置 React 组件中的 className,例如:
    你能进一步解释一下你的意思吗?
  • 所有样式都可以作为普通 css 使用。然后你可以在你的 h3 组件中使用它:&lt;h3 className="h3" &gt;Components&lt;/h3&gt;
  • 我明白你的意思,但我的目标是使用 CSS 模块,其中每个 CSS 文件都在本地范围内(每个反应组件一个 css 文件)。这就是为什么我需要以编程方式分配 className
  • 我明白了,我没有找到任何更好的解决方案,只有这个解决方法。我会关注这个问题,也许你会有运气。
【解决方案4】:

您可以使用https://github.com/Quramy/typed-css-modules,它从 CSS 模块 .css 文件创建 .d.ts 文件。另请参阅https://github.com/css-modules/css-modules/issues/61#issuecomment-220684795

【讨论】:

    【解决方案5】:

    游戏有点晚了,但您可以在与 tree.css 相同的文件夹中创建一个名为 tree.css.d.ts 的文件,其中包含以下行:

    export const h3: string;
    

    并且仍然使用 import 语句 import * as styles from ...,你仍然会得到代码完成和编译时间检查。

    您可以手动管理这些定义文件,也可以将 typed-css-modules 集成到构建管道中 (https://github.com/Quramy/typed-css-modules)

    【讨论】:

      猜你喜欢
      相关资源
      最近更新 更多
      热门标签