Create-react-app + TypeScript + CSS Modules: Auto-generating type definitions without ejecting from CRA
Asked Answered
C

3

16

Problem

create-react-app v2+ supports TypeScript and CSS Modules out of the box... separately. The problem arises when you try to use the two together. Facebook had an extensive discussion about this issue and ultimately closed it off on GitHub. So developers have to use hacks and other workarounds to get these two technologies to play nicely together alongside CRA.

Existing workaround:

You can manually create ComponentName.module.css.d.ts files with type definitions like this: export const identifierName: string. This allows you to take advantage of TypeScript's typing and VS Code's auto-complete when you go to import ComponentName.module.css. Unfortunately, this is extremely tedious.

Solution (?):

The folks over at Dropbox created typed-css-modules-webpack-plugin to address this issue; it auto-genertes those *.d.ts files for you. They show how to install it with yarn or npm and then give this minimal code example:

const path = require('path');
const {TypedCssModulesPlugin} = require('typed-css-modules-webpack-plugin');

module.exports = {
  entry: './src/index.ts',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: 'ts-loader',
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          // Use CSS Modules
          {
            loader: 'css-loader',
            options: {
              modules: true,
            },
          },
        ],
      },
    ],
  },
  // Generate typing declarations for all CSS files under `src/` directory.
  plugins: [
    new TypedCssModulesPlugin({
      globPattern: 'src/**/*.css',
    }),
  ],
};

Unfortunately, it's not immediately clear how I can use this with create-react-app. I'm not very knowledgeable when it comes to Webpack, and I'm using customize-cra to avoid ejecting out of create-react-app so I can customize the Webpack configs for some things I need. For example, Ant Design lets you import components on demand by using babel-plugin-import as detailed here:

https://ant.design/docs/react/use-in-typescript#Use-babel-plugin-import

Question: How can I convert the above Webpack configuration code to a customize-cra equivalent so that I don't have to eject out of CRA?

Comfy answered 14/10, 2019 at 15:45 Comment(0)
C
35

Okay, so I eventually did figure this out, and I wrote a blog post on the subject for anyone who runs into a similar issue:

https://aleksandrhovhannisyan.github.io/blog/dev/how-to-set-up-react-typescript-ant-design-less-css-modules-and-eslint/#3-create-react-app-css-modules-and-typescript-

The solution uses the typescript-plugin-css-modules plugin. Here are the relevant bits from my blog post:

yarn add -D typescript-plugin-css-modules

After it’s installed, add the plugin to your tsconfig.json:

{
  "compilerOptions": {
    "plugins": [{ "name": "typescript-plugin-css-modules" }]
  }
}

Next, create a file named global.d.ts under your src directory. You don’t have to name it global, by the way; you can name the file whatever you want, as long as it has the .d.ts extension. Enter these contents:

declare module '*.module.less' {
  const classes: { [key: string]: string };
  export default classes;
}

If you want to also use SASS or CSS, simply add more module declarations and change the .less extension.

We’re almost done! Per the plugin’s usage instructions, if you want intellisense to work in VS Code, you’ll need to force VS Code to use your workspace version of TypeScript instead of the globally installed version. Remember when we installed TypeScript via CRA at the very beginning? That’s our workspace version of TypeScript.

Here’s how to use the workspace version of TypeScript in VS Code:

  1. Open any TypeScript file.

  2. Click the version number on the blue status bar at the bottom of VS Code.

  3. Select Use Workspace Version (3.7.3 as of this writing).

Here’s a screenshot to make that clearer:

enter image description here

Once you do that, VS Code will create a .vscode directory in your project for workspace settings.

At this point, you're all set to use CSS Modules with TypeScript.

Comfy answered 6/12, 2019 at 22:37 Comment(5)
thanks alex, your link is not working.. updated link aleksandrhovhannisyan.com/blog/dev/…Koren
this solution works. Question owner should tag this as an answer... Thanks AlexXantha
@alexh you rlobg post is downExtranuclear
did I really need the following part ? { const classes: { [key: string]: string }; export default classes; } without it , still work for meBucky
Followed this and Gorr1995s tweak and still didn't work...Dioptrics
D
7

UPDATE 2022

Note: If you're using [email protected] or higher you don't need to use custom definitions if you are using typescript-plugin-css-modules like

declare module '*.module.less' {
  const classes: { [key: string]: string };
  export default classes;
}

Custom definitions

Note: Create React App users can skip this section if you're using [email protected] or higher.

Also you can add this VS code setting to you local JSON settings file:

{
  "typescript.tsdk": "node_modules/typescript/lib",
  "typescript.enablePromptUseWorkspaceTsdk": true
}

This will ensure that VS Code will use the project’s version of Typescript instead of the VS Code version and will prompt you to do so if you aren’t already.

Demurrer answered 11/3, 2022 at 17:36 Comment(1)
The best answer in 2022! Thank you!Papageno
M
2

Well, everything is correct as said AlexH. 1 in tsconfig.ts.

{
  "compilerOptions": {
    "plugins": [{ "name": "typescript-plugin-css-modules" }]
  }
}

2 in global.d.ts

declare module '*.module.less' {
  const classes: { [key: string]: string };
  export default classes;
}
  1. But Also in tsconfig you should write
 "include": [
    "global.d.ts",
     ...
  ]
Marola answered 19/4, 2020 at 12:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.