web-dev-qa-db-fra.com

Utiliser les modules CSS dans les composants React avec TypeScript créé par webpack

Je souhaite utiliser le css-loader avec l'option 'modules' de webpack dans une application React écrite en TypeScript. Cet exemple était mon point de départ (ils utilisent Babel, Webpack et React).

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

Voici un composant de React que je souhaite styler avec un fichier 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;
}

Quoi que je fasse (essayé de changer la syntaxe d'importation, essayé de déclarer le 'require' pour ts-loader, décrit ici , je reçois toujours:

Erreur non capturée: impossible de trouver le module "../../../css/tree.css"

à l'exécution et 

erreur TS2307: impossible de trouver le module '../../../css/tree.css'.

par le compilateur TS. Que ce passe-t-il? Il me semble que css-loader n’émet même pas d’ICSS? Ou est-ce que ts-loader se comporte mal?

18
Shady

import a une signification particulière pour TypeScript. Cela signifie que TypeScript tentera de charger et de comprendre la chose importée. La bonne façon est de définir require comme vous l'avez mentionné, mais alors var au lieu de import:

var styles = require('../../../css/tree.css')`
11
James Brantly
  1. Déclarez 'besoin' selon documentation de ts-loader .
  2. Utilisez 'require' comme générique avec <any> type: require <any> ("../../../ css/tree.css").

fichier * .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;
}; 

Fichier * .tsx avec composant

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

Je sais que la réponse a déjà été donnée, mais cela faisait longtemps que je me débattais avant de comprendre que je devais utiliser la spécification de type générique, sans quoi je ne pourrais pas accéder au contenu du fichier CSS. (J'obtenais l'erreur: La propriété 'h3' n'existe pas sur le type '{}'.)

7
Martin

Vous pouvez utiliser https://github.com/Quramy/typed-css-modules , qui crée des fichiers .d.ts à partir de fichiers CSS Modules .css. Voir aussi https://github.com/css-modules/css-modules/issues/61#issuecomment-220684795

2
Yosuke Kurami

J'ai eu le même problème. Pour moi, les œuvres importent:

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

Webpack change cela comme n'importe quelle autre importation normale. Ça change en

__webpack_require__(id)

Un inconvénient est que vous avez perdu le contrôle de la variable de style.

2
Krzysztof Sztompka

Un peu tard dans la partie, mais vous pouvez créer un fichier nommé tree.css.d.ts dans le même dossier que tree.css contenant cette ligne:

export const h3: string;

et continuez à utiliser l'instruction d'import import * as styles from ... et vous obtiendrez toujours l'achèvement du code et la vérification du temps de compilation.

Vous pouvez soit gérer ces fichiers de définition manuellement, soit intégrer des modules typed-css-modules dans votre pipeline de construction ( https://github.com/Quramy/typed-css-modules )

0
Gareth Evans