CRA: Powerful React Project Setup
Tags: react, vscode, productivity, testing
Published: 2021-06-09 17:03:04

Actually, you can create a bootstrap React project with tools like [CRA: Create React App](https://reactjs.org/docs/create-a-new-react-app.html)

```bash
npx create-react-app <project-name> [--template typescript] --use-npm 
cd <project-name>
```

A shiny clean project was created. But it will need some extra tools to automate tasks that can make your life and the life of your development team easier.

# Project Settings

We will start with the VSCode configurations. Creating a `.vscode` folder with a `settings.json` file inside.

```json
{
    "emmet.excludeLanguages": [],
    "emmet.includeLanguages": {
        "markdown": "html",
        "javascript": "javascriptreact",
        "typescript": "typescriptreact"
    },
    "emmet.showSuggestionsAsSnippets": true,
    "emmet.triggerExpansionOnTab": true,
    "files.exclude": {
        "**/*.js.map": {
            "when": "$(basename)"
        },
        "**/node_modules": true,
    },
    "html.autoClosingTags": true,
    "javascript.autoClosingTags": true,
    "javascript.suggest.completeFunctionCalls": true,
    "typescript.suggest.completeFunctionCalls": true,
    "javascript.inlayHints.functionLikeReturnTypes.enabled": true,
    "typescript.inlayHints.functionLikeReturnTypes.enabled": true,
    "javascript.inlayHints.parameterNames.enabled": "all",
    "typescript.inlayHints.parameterNames.enabled": "all",
    "javascript.suggest.autoImports": true,
    "search.exclude": {
        "**/coverage": true,
        "**/node_modules": true
    },
    "typescript.autoClosingTags": true,
    "typescript.suggest.autoImports": true,
}
```
<figcaption>/.vscode/settings.json</figcaption>
  
> There are a lot of VSCode extensions and configurations out there. If you are hungry for more check [VSCode - Essentials](https://dev.to/equiman/my-essential-visual-studio-code-extensions-and-configurations-5197) and [VSCode - React Flavored](https://dev.to/equiman/vscode-react-flavored-134h).

---

It's recommended to make these configurations on **project settings** and not in the global settings.

## JS Linter

- [ES Lint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) extension

```json
{
    "editor.formatOnSave": true,
    "javascript.format.enable": false,
    "javascript.validate.enable": true,
    "typescript.format.enable": false,
    "typescript.validate.enable": true,
}
```
<figcaption>/.vscode/settings.json</figcaption>
  
Install and config on the project folder:

```bash
npm install -D eslint
npx eslint --init
```

You can choose the better for you, but my opinionated configurations are:

```bash
Use: To check syntax, find problems, and enforce code style
Type of modules: JavaScript modules (import/export)
Framework: React
Typescript: No #or Yes if the project uses it
Run: Browser #and Node if use Next.js
Style guide: Popular -> Standard #JS without semi-colon ;
Format: JavaScript
```

You will be asked to install extra packages. Answer **yes**. 

> **Semi-colon exception**  
> Because the `standard` style guide does not use semi-colons (`;`) take this in mind. If the next statement right after the line without a semicolon starts with one of the following special operators `[`, `(`, `+`, `\`*, `/`, `-`, `,`, `.`, it will be recognized as an expression to the previous statement. Then you are going to need to start the line with `;`.

When finish update configurations `rules`:

```javascript
{
  rules: {
    'no-console': 'warn',
    'react/prop-types': "off",
    'react/self-closing-comp': 'warn',
    'padding-line-between-statements': [
      'error',
      {'blankLine': 'always', 'prev': '*', 'next': 'return'},
      {'blankLine': 'always', 'prev': ['const', 'let', 'var'], 'next': '*'},
      {'blankLine': 'any', 'prev': ['const', 'let', 'var'], 'next': ['const', 'let', 'var']}
    ]
  },
  settings: {
    react: {
      version: 'detect',
    },
  },
}
```
<figcaption>.eslintrc.js</figcaption>

Create a `.eslintignore` file on the root of the folder project:

```config
build
coverage
dist
```

> There is no need to add `node_modules` because it was ignored by default.
  
If you don't want to use eslint extensions, add `list` and `fix` command *at end* of `scripts`:

```diff
{
  "scripts": {
+    "lint:l": "eslint .",
+    "lint:f": "eslint . --fix --ext .js,.jsx,.ts,.tsx"
  }
}
```
<figcaption>package.json</figcaption>

### Avoid import React error

> Since React 17, you don't need to `import React` to use JSX anymore. But we would still need to import React to use Hooks or other exports that React provides.

> To avoid ESLint warns about import React, add a plugin:

```diff
{
  extends: {
+    'plugin:react/jsx-runtime',
  }
}
```
<figcaption>.eslintrc.js</figcaption>

### Auto sort imports and properties

If you don't want to deal with sorting set this configuration.

```diff
{
  rules: {
+    "import/order": ["warn", {
+      "pathGroups": [{
+        "pattern": "~/**",
+        "group": "external",
+        "position": "after"
+      }],
+      "newlines-between": "always-and-inside-groups"
+    }],
+    "react/jsx-sort-props": [
+      "warn",
+      {
+        "callbacksLast": true,
+        "shorthandFirst": true,
+        "noSortAlphabetically": false,
+        "reservedFirst": true
+      }
+    ],
  },
}
```
<figcaption>.eslintrc.js</figcaption>
  
---

> ESLint can be enough, and Prettier it's optional because have a little better performance formatting than ESLint. If you want to use it go ahead.

## JS Format

- [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) extension

```diff
{ 
+    "[javascript][typescript]": {
+        "editor.defaultFormatter": "esbenp.prettier-vscode"
+    }
}
```
<figcaption>/.vscode/settings.json</figcaption>
  
Install Prettier and ESLint for prettier:

```bash
npm install -D prettier eslint-config-prettier
```

Create a `.prettierignore` file on the root of the folder project:

```config
build
coverage
dist
package-lock.json
```

> There is no need to add `node_modules` because it was ignored by default.

Create a `.prettierrc.json` file on the root of the folder project:

```json
{
    "semi": false,
    "singleQuote": true
}
```

Add extends prettier configuration *at the end* of `extends`:

```diff
{
  extends: [
+    'prettier'
  ]
}
```
<figcaption>.eslintrc.js</figcaption>
  
If you don't want to use prettier extensions, add `check` and `write` command *at end* of `scripts`:

```javascript
{
  "scripts": {
+    "prettier:c": "prettier . --check",
+    "prettier:w": "prettier . --write"
  }
}
```
<figcaption>package.json</figcaption>

---

## HTML Linter

- [HTMLHint](https://marketplace.visualstudio.com/items?itemName=mkaufman.HTMLHint)

```bash
npm install --global htmlhint
```

If you also want to lint HTML with ESLint install this additional plugin:

```bash
npm install -D eslint-plugin-html
```

And add `html` to the list of plugins

```diff
{
  plugins: [
    'react',
+    'html'
  ],
}
```
<figcaption>.eslintrc.js</figcaption>

---

## CSS Linter

- [Stylelint](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint) extension

Install and config on the project folder:

```bash
npm install -D stylelint stylelint-config-standard
```

Create a configuration file named .stylelintrc.json in the top level of your repository.

```json
{
  "extends": "stylelint-config-standard",
  "rules": {
    "declaration-colon-newline-after": "always-multi-line",
    "property-no-unknown": [ true, {
      "ingnoreProperties": ["content-visibility"] 
    }]
  },
  "ignoreFiles": [
    "build/**",
    "coverage/**",
    "dist/**",
    "**/*.js",
    "**/*.jsx", 
    "**/*.ts",
    "**/*.tsx" 
  ] 
}
```

To prevent both VS Code's built-in linters and Stylelint from reporting the same errors, you can disable the built-in linters.

```diff
{ 
+    "stylelint.enable": true,
+    "css.validate": false,
+    "less.validate": false,
+    "scss.validate": false,
+    "[css][scss]": {
+        "editor.defaultFormatter": "stylelint.vscode-stylelint"
+    }
}
```
<figcaption>/.vscode/settings.json</figcaption>

Stylelint has more than 170ish rules. Sometimes it will show you an error that will literally cause a problem.

---

## Git Linter

- [Lint Staged](https://github.com/okonet/lint-staged)

It works over [Husky](https://github.com/typicode/husky) and only runs linters against staged git files. By doing so you can ensure no errors go into the repository and enforce code style.

Install and config on the project folder:

```bash
npx mrm@3 lint-staged
```

---

## Testing

- [Jest](https://jestjs.io/)

Add jest environment support at end of `env`:

```diff
{
  env: {
+    jest: true,
  },
}
```
<figcaption>.eslintrc.js</figcaption>

### Auto update threshold

If you want to update automatically the coverage threshold use this package.

```bash
npm install -D jest-coverage-thresholds-bumper
```

Add test update *at end* of `scripts`, create a `jest` section and update the `lint-staged` scripts:

```diff
{
  "scripts": {
+    "test:c": "react-scripts test --coverage --watchAll=false --ci",
+    "test:cw": "react-scripts test --coverage --watchAll",
+    "test:r": "open ./coverage/lcov-report/index.html",
+    "coverage:tb": "jest-coverage-thresholds-bumper --margin 1"
+  },
+  "jest": {
+    "coverageReporters": [
+      "text",
+      "html",
+      "lcov"
+    ],
+    "coverageThreshold": {
+      "global": {
+        "statements": 0,
+        "branches": 0,
+        "functions": 0,
+        "lines": 0
+      }
+    }
+  },
+  "lint-staged": {
+    "*.{js,jsx,ts,tsx}": [
+      "eslint --cache --fix"
+    ],
+    "*.{css,scss}": [
+      "stylelint --fix"
+    ],
+    "*.{js,jsx,ts,tsx,css,md}": "prettier --write"
+  }
}
```
<figcaption>package.json</figcaption>
  
---

## Debug

- [clic-to-component](https://github.com/ericclemmons/click-to-component) ⭐

It's not an extension. It is an `npm` package to install on your project that helps with debugging process.

```bash
npm install -S click-to-react-component
```

Even though `click-to-react-component` is added to `dependencies`, [tree-shaking](https://esbuild.github.io/api/#tree-shaking) will remove `click-to-react-component` from `production` builds.

![beam me up](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/clcw1jzihrlwzx3dfq7t.gif)

With a combination of keys and clicking over the component in the browser, it will **transport** you to the source component in your editor.

![clic-to-component](https://github.com/ericclemmons/click-to-component/raw/main/.github/cra.gif)

Works with `CRA`, `vite`, and Next adding these configurations on your project:

```diff
+import { ClickToComponent } from "click-to-react-component";
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./index.css";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
+   <ClickToComponent />
    <App />
  </React.StrictMode>
);
```

---

## Styles

- Sass(https://sass-lang.com/)

If you want still to use Sass. CRA has `SCSS` built support. Install this package:

```bash
npm install -D sass
```

> Take care of using `sass` and not `node-sass` package because is deprecated.

If you decided to use Stylelint. Add this package: 

```bash
npm remove stylelint-config-standard stylelint-config-prettier
npm install --D stylelint-config-standard-scss stylelint-config-prettier-scss
```

Add it as extends on `.stylelintrc.json` file 

```diff
{
  "extends": [
    ..., 
-    "stylelint-config-standard",
+    "stylelint-config-standard-scss",
-    "stylelint-config-prettier",
+    "stylelint-config-prettier-scss",
  ]
}
```

Now rename manually all `.css` files to `.scss` and update `src/App.js` to import `src/App.scss`. This file and any other file will be automatically compiled if imported with the extension `.scss`.

---

**That’s All Folks!
Happy Coding** 🖖

[![beer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mkgsx4aw6qn9i9ax6as9.png)](https://github.com/sponsors/deinsoftware)