Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 530
AlexH Avatar asked Oct 14 '19 15:10

AlexH


1 Answers

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.

like image 160
AlexH Avatar answered Sep 26 '22 15:09

AlexH