Let’s skip the exposition and just jump right in. I’ll use VS Code to make my life easier; I recommend that you do the same. Note that I’ll be using yarn as my package manager, but you can also use npm.

1. Setting up Create React App with TypeScript 💻

Switch to your target project directory and run this command:

npx create-react-app . --template typescript

Alternatively, if your project directory does not yet exist, you can create it in one go:

npx create-react-app new-project-dir-name --template typescript

This uses Facebook’s create-react-app to initialize a React project with TypeScript. React by itself is pretty powerful, but React with TypeScript is a much, much better dev experience, in my opinion.

Note: You may come across older tutorials that simply pass in the --typescript flag to this command. That used to work, but it was recently deprecated. CRA now uses the template flag.

Here’s what your directory structure and package.json should roughly look like once that’s done:

The directory structure of a CRA project.

Version numbers may obviously differ.

Beyond this point, most people have trouble overriding Create React App’s Webpack configs without ejecting. Fortunately, as we’ll see shortly, it’s not all that difficult!

2. Setting Up Ant Design and LESS 🎨

Ant Design is a fantastic library for React and other JavaScript frameworks that provides reusable and customizable components, like date pickers, lists, SVG icons, and lots of other cool stuff. Let’s set it up.

Installing Ant Design

Run this command:

yarn add antd

Note that antd already comes with type definitions, so there’s no need to install @types/ for it.

Importing Antd Components on Demand

Typically, to use an Ant Design component, you’d have to import the component from a specific directory under antd as well as import its accompanying stylesheet:

import Button from 'antd/es/button';
import 'antd/es/button/style';

Urgh. This kinda sucks.

Instead, we can follow Ant Design’s guide in order to load components with a simple import like this:

import { Button } from 'antd';

First, install the babel-plugin-import package:

yarn add -D babel-plugin-import

Then install the react-app-rewired and customize-cra packages:

yarn add react-app-rewired customize-cra

These allow us to customize create-react-app without ejecting.

Change the scripts in your package.json to use react-app-rewired:

package.json
"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject"
}

Create a file named config-overrides.js at the root of your project directory with this code:

config-overrides.js
const { override, fixBabelImports } = require('customize-cra');

module.exports = override(
  fixBabelImports('import', {
    libraryName: 'antd',
    libraryDirectory: 'es',
    style: 'css'
  })
);

Now, you can import antd components in your source files like you would from any other package, without having to additionally specify the stylesheet or the specific lib path to import from.

Let’s try it out. Open up your App.tsx and replace it with the following:

src/App.tsx
import React from 'react';
import { Button } from 'antd';

const App = () => {
  return (
    <main
      style={{
        height: '500px',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'center',
        alignItems: 'center'
      }}
    >
      <Button type="primary">Hello, Ant Design!</Button>
      <a href="foo.bar">I'm a link. Click me, please!</a>
    </main>
  );
};

export default App;

If your app was already running, you’ll need to restart it to observe these new changes.

Here’s the result once you do that:

An Ant Design button and anchor.

Customize the Ant Design Theme with LESS

Let’s say you want to use a different primary color or base font size. Easy peasy!

First, install the less and less-loader packages:

yarn add less less-loader

Then, simply add a LESS loader to your config overrides:

config-overrides.js
const { override, fixBabelImports, addLessLoader } = require("customize-cra");

module.exports = override(
  fixBabelImports("import", {
    libraryName: "antd",
    libraryDirectory: "es",
    style: true,
  }),
  addLessLoader({
    lessOptions: {
      javascriptEnabled: true,
      modifyVars: {
        "@primary-color": "#f48549", // customize as needed
        "@link-color": "#e6a07c", // customize as needed
        "@font-size-base": "18px", // customize as needed
      },
    },
  })
);

Note: Be sure to check this issue if you run into any problems. customize-cra and less-loader have had compatibility issues in the past.

That’s it! Restart your app again to see the new results in your browser:

An Ant Design button and anchor, styled using a custom color.

The best part is that Ant Design’s UI is consistent, using shades of your primary color for all components to give your app a cohesive, branded look.

If you want to customize Ant Design’s theme even more, check out their list of supported variables.

3. Create React App CSS Modules and TypeScript 📦

By default, create-react-app v2 ships with CSS Modules out of the box.

But how do we use CSS Modules with TypeScript?

This was an absolute headache to deal with before. But now, there’s a package that does just what we want, and it’s made by a tech lead on Facebook’s CRA team!

yarn add -D typescript-plugin-css-modules

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

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

Next, create a file named global.d.ts under your src directory. You can actually name this file whatever you want, as long as it has the .d.ts extension. Paste in this module declaration:

src/global.d.ts
declare module '*.module.less' {
  const classes: { [key: string]: string };
  export default classes;
}

Want to use Sass or CSS instead of Less? No problem! Simply replace the .less extension.

We’re almost done! Per the plugin’s usage instructions, 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:

Using the workspace version of TypeScript in VS Code.

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

With that out of the way, let’s now create a LESS stylesheet for our App component to move all the styles from before out of our JS. Name it App.module.less and fill it with these rules:

src/App.module.less
.app {
    align-items: center;
    display: flex;
    flex-direction: column;
    height: 500px;
    justify-content: center;
}

Then, import the stylesheet like this in your component file:

src/App.tsx
import styles from './App.module.less';

If you now try to access styles.app or styles.whateverClassOrIDYouWant, you may not see the auto-complete suggestions immediately. That doesn’t mean that your installation is broken, though—this is just a known VS Code issue.

The solution is to simply open up the VS Code command palette (Ctrl+Shift+P on Windows and Cmd+Shift+P on Mac) and do Developer: Reload Window. Then simply wait for VS Code to re-initialize TypeScript intellisense (keep an eye on the bottom-left of the status bar). Here’s a demo:

Reloading VS Code and waiting for TypeScript to initialize.

Once that’s done, you won’t have to guess or remind yourself what you named your CSS classes/IDs:

VS Code autocomplete for TypeScript CSS Modules.

Awesome! 😎 Here’s what App.tsx should look like if you’ve been following along:

src/App.tsx
import React from 'react';
import { Button } from 'antd';
import styles from './App.module.less';

const App = () => {
  return (
    <main className={styles.app}>
      <Button type="primary">Hello, Ant Design!</Button>
      <a href="foo.bar">I'm a link. Click me, please!</a>
    </main>
  );
};

export default App;

Refresh the page, and you’ll see that it looks exactly the same, except we now get to take advantage of CSS Modules and LESS (as well as potentially SASS or vanilla CSS, if you’d like to use those instead).

4. Using ESLint with Create React App and Prettier 💅

We could stop there, and put up with garbo code formatting and inconsistencies, and create more work for our collaborators as they try to reconcile several people’s style preferences.

But why, why would you do that? Why would you do any of that?

Or we could set up ESLint with Prettier to format our code consistently 🙂

First, install these packages:

yarn add -D @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-prettier eslint-config-react eslint-plugin-prettier prettier

(Credit goes to Ben Weiser for figuring this part out.)

Next, create a file named .eslintrc.json at the root of your project directory with this JSON:

.eslintrc.json
{
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier/@typescript-eslint",
    "plugin:prettier/recommended"
  ],
  "plugins": ["react", "@typescript-eslint", "prettier"],
  "env": {
    "browser": true,
    "jasmine": true,
    "jest": true
  },
  "rules": {
    "prettier/prettier": ["error"],
    "@typescript-eslint/explicit-member-accessibility": 0,
    "@typescript-eslint/explicit-function-return-type": 0,
    "react/no-unescaped-entities": 0
  },
  "settings": {
    "react": {
      "pragma": "React",
      "version": "detect"
    }
  },
  "parser": "@typescript-eslint/parser"
}

Create another file named .prettierrc at the root of your project directory with these contents:

.prettierrc
{
  "singleQuote": true,
  "printWidth": 80,
  "trailingComma": "es5"
}

This is where you’ll define all your Prettier formatting rules. You could technically define these under rules in your eslintrc file, but I prefer to keep them separate. Also, note that you don’t have to use these exact rules; you can change them if you’d like to.

If You’re Not Using VS Code

Add a lint:fix script to your package.json so you can fix linting errors as needed (you can name this script something else if you’d like to). This is what your scripts should look like:

package.json
"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject",
    "lint:fix": "eslint --fix './src/**/*.{ts,tsx}'"
}

Then, you can simply run yarn lint:fix from your terminal.

If You Are Using VS Code

You can still use the above script, but I highly recommend that you also install these two VS Code extensions:

At this point, you may not see any linting errors highlighted in VS Code, no matter how much you try to mess up your files—and that’s because we need to add some rules to our VS Code settings.

Open up your command palette again (Ctrl+Shift+P on Windows and Cmd+Shift+P on Mac) and type settings. Then, click on Preferences: Open Settings (JSON):

Opening user settings via the VS Code command palette.

Stick this somewhere inside the existing JSON blob:

"[typescript]": {
  "editor.formatOnSave": true,
  "editor.tabSize": 2
},
"[typescriptreact]": {
  "editor.formatOnSave": true
},
"eslint.enable": true,
"eslint.validate": [
  "javascript",
  "javascriptreact",
  "typescript",
  "typescriptreact"
],
"editor.codeActionsOnSave": {
  "source.fixAll.eslint": true
}

Note: You could also just put this in your workspace settings, but then you’d have to do that for every project. If you only want to lint for this project, select Preferences: Open Workspace Settings instead.

If all went well, VS Code should now underline linting errors with red squiggly lines. And when you save a file with linting errors, ESLint will automatically fix them for you!

Let’s mess up App.tsx on purpose to see this in action:

Auto-fixing linting errors in VS Code.

Note that some linting errors may still need to be corrected manually if there are no automatic fixes available. But this works for a majority of errors you’ll come across, allowing you to code much more quickly and in whatever style you prefer.

That About Does It! 🎉

You’re all set for a more pleasant dev experience with create-react-app.

With everything set up, you can now create a separate folder for your components and rearrange your files as you please.

I hope you found this tutorial helpful!

💬 Comments

Post comment
Loading...