The Nx Node/React Stack part 1 - Environment
Tags: git, prettier, eslint, githooks
Published: 2023-07-22 16:59:56

> Modern web development is fantastic. There are so many great tools available!
Modern web development is exhausting. There are so many great tools available!
Kent C. Dodds

This will be a long series shows strong opinions of how to build an nx node/react stack application.

### When to use this stack?

1. When you are comfortable with node/react & typescript.
2. When you want to build a MVP, or start with a team while having minimal configuration.
3. If you have `take home project` interviewing for a senior role and you want to show your knowledge across the stack, this is especially helpful in mid-sized to small companies.

> tldr; now will set up nx, prettier, eslint & husky in a matter of minutes.

Prerequisites for this series
* NodeJs
* Npm
* VsCode
* Terminal


In this series we will be building a simple markdown editor.

But before starting out into coding, we need to address the elephant in the room [Nx](https://nx.dev/) monorepo

### What is a monorepo?

Based on the definition from the [official site](https://monorepo.tools/)
> A monorepo is a single repository containing multiple distinct projects, with well-defined relationships.

### Why using Nx for monorepos?
in short:
Nx helps to: speed up your computation (e.g. builds, tests etc), locally and on CI and to integrate and automate your tooling via its plugins. All of this can be adopted incrementally. You can use plugins, but you don't have to.

We can simplify the need with the followings:
1. Testing libraries, Jest & cypress and sat up by default.
2. Easily navigating between projects and reduce communication needed.
3. Code sharing between projects, yes you can but with governing rules that we will go to in the next chapters
4. Under the hood micro frontend support.
5. With learning monorepos, you can easily board into bigger companies that have microservices implemented and you have ownership for parts of the system.

## Setup table of content
  * [1. Create the monorepo](#chapter-1)
  * [2. Prettier setup](#chapter-2)
  * [3. Linting setup](#chapter-3)
  * [4. Husky aka git-hooks](#chapter-4)


## 1. Create the monorepo <a name="chapter-1"></a>

We need to specify the 

```shell
npx create-nx-workspace@latest
```

It will take you through a terminal dialog that contains the following steps:

1. Where would you like to create your workspace? [awesome-editor]
2. Which stack do you want to use? [ts]
3. Standalone project or integrated monorepo? [integrated]
4. Enable distributed caching to make your CI faster? [Yes]

![nx workspace setup successfully](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6juqr7li2mq5bn3pfr0m.png)


## 2. Prettier set up <a name="chapter-2"></a>

If you have in the package.json prettier, just remove it from the dependencies, then run the following command
```shell
npm uninstall prettier && npm install prettier --save-dev
```
now create `.prettierrc` where it will contain the following json object
```json
{
  "trailingComma": "es5",
  "tabWidth": 4,
  "semi": false,
  "singleQuote": true
}
```
Now we need to ignore some files from the prettier using `.prettierignore`

```txt
/dist
/coverage

```
now add the following command into `package.json` scripts 

```json
"format": "prettier --write ."
```

## 3. Linting set up <a name="chapter-3"></a>

first we need to install our eslint & plugins,
Note: if you have in the package.json prettier, just remove it from the dependencies, then run the following command
```shell
npm uninstall eslint && npm install eslint --save-dev
```
We can go and add the linting through the command, but here I will add it manually.


```shell
npm i eslint-config-prettier eslint-plugin-prettier eslint-plugin-storybook eslint-plugin-unicorn @nx/eslint-plugin @typescript-eslint/eslint-plugin@5.62.0 @typescript-eslint/parser --save-dev
```

The above rules are our essentials, here are some other rules you 'can' consider:
- eslint-config-next 
- eslint-plugin-react 
- eslint-plugin-react-button-has-type 
- eslint-plugin-react-hooks

Now, we need to create the `.eslintignore`

```txt
/node_modules
/dist
# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
```
now let's create the `.eslintrc.json`

```json
{
  "root": true,
  "ignorePatterns": ["**/*"],
  "parser": "@typescript-eslint/parser",
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:unicorn/recommended",
    "plugin:storybook/recommended"
  ],
  "plugins": ["@typescript-eslint", "prettier", "@nx", "custom-rules"],
  "overrides": [
    {
      "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
      "rules": {
        "@nx/enforce-module-boundaries": [
          "error",
          {
            "enforceBuildableLibDependency": true,
            "allow": [],
            "depConstraints": [
              {
                "sourceTag": "*",
                "onlyDependOnLibsWithTags": ["*"]
              }
            ]
          }
        ]
      }
    },
    {
      "files": ["*.ts", "*.tsx"],
      "extends": ["plugin:@nx/typescript"],
      "rules": {}
    },
    {
      "files": ["*.js", "*.jsx"],
      "extends": ["plugin:@nx/javascript"],
      "rules": {}
    }
  ]
}
```

As you can see we added a extension called `custom-rules`
we need to set it up, this way you can modify the existing linting and compilation rules.


```shell
mkdir eslint-custom-rules
cd ./eslint-custom-rules
npm init
touch index.js
mkdir ./rules # here the rules will live
```
To link the custom-rules with existing codebase go to `package.json` to `devDependencies`
and the following code
```json
"eslint-plugin-custom-rules": "file:eslint-custom-rules"
```


Now go to `package.json` and add the following linting the command.
```json
"scripts": {
    "lint": "eslint --fix --ext .js --ignore-path .eslintignore",
    "format": "prettier --write ."
  }
```

## 4. Set up git hooks <a name="chapter-4"></a>

```
git init
npx husky-init && npm install
```

Then go to `./.husky/pre-commit` and comment the test run, we currently don't have any tests to cover and add the linting command
```shell
#npm run test
npm run lint
```

Now when you try to commit, husky will check if there are linting issues occurred at first, in later stages we will add tests where you can't commit unless tests are green.


# Conclusion

Modern web development offers a plethora of fantastic tools, making the process both exciting and overwhelming. In this blog series, I guide you through setting up a monorepo for your server and client sides using `Nx`, a powerful tool providing numerous benefits such as accelerated computation, local and CI optimizations, and tooling integration through plugins. We begin by creating the monorepo using `create-nx-workspace`, followed by setting up Prettier for code formatting consistency. Then, we configure `ESLint`, incorporating various plugins to maintain code quality and catch issues early. Finally, we establish `Git hooks` with `Husky`, ensuring codebase adherence to linting rules before each commit. By following this series, you'll create a well-organized, efficient, and maintainable monorepo, streamlining your modern web development workflow. Embrace the opportunities provided by Nx and other technologies to enhance productivity and coding experience.