在 React 组件中使用 CSS 模块和 webpack 构建的 Typescript

Use CSS Modules in React components with Typescript built by webpack

本文关键字:webpack 构建 Typescript 模块 CSS 组件 React      更新时间:2023-09-26

我想在用 Typescript 编写的 React 应用程序中使用 css 加载器和 webpack 的"modules"选项。这个例子是我的起点(他们正在使用 Babel、webpack 和 React)。

网络包配置

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")()]
    }
}

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

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

树.css

.h3{
    color: red;
}

无论我在做什么(尝试更改导入语法,尝试声明 ts-loader 的"要求",如此处所述,我总是得到:

未捕获错误:找不到模块"../../../css/tree.css"

在运行时和

错误 TS2307:找不到模块"../../../css/tree.css'.

由 TS 编译器提供。这是怎么回事?在我看来,css加载器甚至没有发出ICSS?还是 ts 加载器行为错误?

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

var styles = require('../../../css/tree.css')`
  1. 根据 ts-loader 文档声明"require"。
  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"。

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

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

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

__webpack_require__(id)

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

您可以使用

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

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

export const h3: string;

并且仍然使用 import 语句import * as styles from ...,您仍将获得代码完成和编译时检查。

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