cssreactjstypescriptwebpackcss-modules

How can you use CSS modules together with Typescript, React and Webpack?


I am building just a reusable component on React and therefore I am not building with react-create-app and trying to configure everything from scratch.

My problem is I keep getting the following error: TS2307: Cannot find module './styles/styles.css' or its corresponding type declarations.

The code is simple at the moment and looks like this:

import React from "react";
import ReactDOM from "react-dom";
import styles from "./styles/styles.css";

const Calendar: React.FC = () => (
  <h1 className={styles.test}>

Here is my webpack configuration:

const config: webpack.Configuration = {
  entry: "./src/index.tsx",
  module: {
    rules: [
      {
        test: /\.(ts|js)x?$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: [
              "@babel/preset-env",
              "@babel/preset-react",
              "@babel/preset-typescript",
            ],
          },
        },
      },
      {
        test: /\.css$/,
        use: [
          "style-loader",
          {
            loader: "typings-for-css-modules-loader",
            options: {
              modules: true,
              namedExport: true,
            },
          },
        ],
      },
    ],
  },
  resolve: {
    extensions: [".tsx", ".ts", ".js"],
  },
  output: {
    path: path.resolve(__dirname, "build"),
    filename: "bundle.js",
  },
  devServer: {
    contentBase: path.join(__dirname, "build"),
    compress: true,
    port: 4000,
  },
  plugins: [
    new ForkTsCheckerWebpackPlugin({
      async: false,
      eslint: {
        files: "./src/**/*",
      },
    }),
  ],
};

What am I missing here? As far as I researched typings-for-css-modules-loader is a drop-in replacement for css-loader that generates typings for CSS on the fly so typeScript shouldn't be a problem?

Here are my relevant dev dependencies:

>     "@babel/core": "^7.12.7",
>     "@babel/plugin-transform-runtime": "^7.12.1",
>     "@babel/preset-env": "^7.12.7",
>     "@babel/preset-react": "^7.12.7",
>     "@babel/preset-typescript": "^7.12.7",
>     "@babel/runtime": "^7.12.5",
>     "@types/fork-ts-checker-webpack-plugin": "^0.4.5",
>     "@types/react": "^17.0.0",
>     "@types/react-dom": "^17.0.0",
>     "@types/webpack": "^4.41.25",
>     "@types/webpack-dev-server": "^3.11.1",
>     "babel-loader": "^8.2.1",
>     "css-loader": "^5.0.1",
>     "fork-ts-checker-webpack-plugin": "^6.0.3",
>     "style-loader": "^2.0.0",
>     "ts-node": "^9.0.0",
>     "typescript": "^4.1.2",
>     "typings-for-css-modules-loader": "^1.7.0",
>     "webpack": "^5.6.0",
>     "webpack-cli": "^4.2.0",
>     "webpack-dev-server": "^3.11.0"

Solution

  • This is the configuration that solved the issue for me:

         {
            test: /\.css$/i,
            use: [
              "style-loader",
              "@teamsupercell/typings-for-css-modules-loader",
              {
                loader: "css-loader",
                options: { modules: true },
              },
            ],
          },
        ],
      },
      resolve: {
        extensions: [".tsx", ".ts", ".js", ".css", ".scss"],
      },