Easy Configuration of ESLint, Cypress, StoryBook, and Prettier for Angular Projects with Nx
Tags: nx, typescript, frontend, angular
Published: 2023-07-30 05:28:17

As an Angular enthusiast, I frequently create solutions that consist of multiple projects, such as apps and libraries. The Angular CLI is instrumental in managing these projects through Angular workspaces.

I often use Angular in conjunction with other tools, including:

* [ESLint:](https://eslint.org/) Facilitates static code analysis.
    
* [Prettier](https://prettier.io/): Simplifies code formatting.
    
* [Jest](https://jestjs.io/) and [Cypress](https://www.cypress.io/): Enable component testing and end-to-end testing.
    
* [Storybook](https://storybook.js.org/): Aids in developing isolated components, which is highly beneficial for testing and documentation.
    

These tools are crucial in my projects to ensure quality and streamline the development process, making it both safe and easy.

Given that I use Angular CLI, I will demonstrate the process of setting up these tools for a small project and discuss the amount of work involved:

## **Scenario**

I'm building a solution for the NBA App, which has two modules: Players, Teams, and an NBA UI Components Library.

Because I'm using AngularCLI, I need to do the following for my projects:

* Create the [workspace](https://angular.io/guide/file-structure): It helps to store multiple projects.
    
* Create App: Angular Application.
    
* Create the Library: NPM UI Library.
    

```bash
ng new --create-application=false nba 
ng generate application nba-web 
ng generate library nba-ui --prefix nba
```

Great, we've created the projects. Now we need to configure the tools for the web project and nba-ui.

Since I don't want to make the article longer, I will do this for the nba-web:

## Set up ESLint, Prettier, Jest, Cypress, and Storybook

### ESLint

It provides schematics to make the installation a bit easier.

```bash
ng add @angular-eslint/schematics
```

> Read more about [configuring ESLint in Angular](https://github.com/angular-eslint/angular-eslint)

### Prettier

It requires installing the Prettier package and adding a few configuration files:

```bash
npm install prettier --save-dev
```

Add the .prettierrc.json and .prettierignore files in the root with basic rules and set up the npm task in the package.json.

> *Read more about configuring* [*Prettier in Angular*](https://prettier.io/docs/en/install.html)

### Jest

Similar to Prettier, we need to install the package and create some configuration files.

```bash
npm install jest jest-preset-angular --save-dev
```

Create a `setup-jest.ts` file in the root and import `jest-preset-angular`

```typescript
import 'jest-preset-angular';
```

Edit the `package.json` to add the Jest configuration and update the script to run jest.

```json
"scripts": {
    "test": "jest"
  }
{
  "jest": {
    "preset": "jest-preset-angular",
    "setupTestFrameworkScriptFile": "<rootDir>/setup-jest.ts"
  }
}
```

> *Read more about configuring* [*Jest in Angular*](https://timdeschryver.dev/blog/integrate-jest-into-an-angular-application-and-library#adding-jest)

### Cypress

It's easier because after installing the package, we can open a wizard with the configuration steps.

Let's add Cypress to the nba-web by running the following command:

```bash
npm install cypress -D
```

And open cypress:

```bash
npx cypress open
```

We need to follow the configuration wizard and choose the type of testing we want to use, either end-to-end (e2e) or component testing.

> Read more about installing [Cypress in Angular](https://docs.cypress.io/guides/getting-started/installing-cypress)

### Storybook

Similar to Cypress, the package handles the configuration, so you only need to run the following command:

```bash
npx storybook@latest init
```

> *Learn more about* [*Storybook in Angular*](https://storybook.js.org/docs/angular/get-started/install)

Alright, I just started with the NBA-web project, and we have the NBA-UI library pending. What happens if tomorrow we want to split our project or add more projects to the workspace and include the same tools?

Crazy, right? Thankfully, we can easily handle all these configurations using [NX](https://nx.dev/).

## What Is Nx?

It's a build system that makes our lives easier by managing monorepos or standalone applications without hassle.

It helps to quickly and easily configure tools like Cypress, Jest, Storybook, ESLint, and more in applications. Nx offers plugins for other frameworks, but I'll be using Angular.

> Learn more about [Nx Packages](https://nx.dev/packages)

The best way to learn about Nx and see how easy it is to work with it is by following the same steps but using Nx; let's get started.

### Setup Workspace

Nx provide the command to create the workspace; it provides a list of options for React, Node or Angular

To create the workspace, we run the command \`npx create-nx-workspace\`, which prompts us to choose the type of workspace we want.

* The name of our workspace: \`nba\`
    
* Which technology? Angular
    
* What kind of workspace: standalone single app or multiple projects? Since we want an Angular application with a UI library, choose integrated.
    
* Next, it asks about the configuration of our Angular application, similar to AngularCLI. It also asks if you want it to be a standalone application (moduleless).
    

Nx enables distributed caching to speed up our build and CI processes. It is free for open-source projects.

Create your workspace by running the command `npx create-nx-workspace@latest`


![Create your workspace ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b9oyehlge0i7mu237mkd.png)

> The outcome is a workspace prepared with Angular, Cypress, ESLint, and Prettier using just one command.


![workspace prepared with Angular, Cypress, ESLint, and Prettier](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8zm1c3yzod52hh90vjpi.png)

## Create The Library

Nx offers a variety of commands for creating libraries, apps, generating components, and more.

Navigate to the NBA directory and create the library by using `nx g @nx/angular` along with the lib parameter and the library name.

```bash
cd nba
nx g @nx/angular:lib nba-ui
```


![lib nba-ui](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vkf0t8j8m3nu5tlya1t1.png)

The result is a library set up with ESLint and Jest effortlessly.


![ library set up with ESLint and Jest effortlessly](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uxum1cvsublmzqvg8rif.png)

### What about Storybook ?

Nx provides a list of packages for our projects to configure with a single command in our projects, for example, Storybook.

We're going to easily configure Storybook without any pain by running the nx configuration command in the nba-ui library.

```bash
nx g @nx/angular:storybook-configuration nba-ui
```

It will ask if you want to configure Cypress to run against the Storybook instance or generate stories from our components in the library, saving a lot of time.


![ generate stories from our components in the library](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3r6ydrmdi9cgdmzlygz4.png)

Ok, lets see if how nx save time and generate stories ?

First, create a navigation and button component using nx, similar to `angular/cli`, by using the `--standalone` flag and specifying the project.

```bash
nx g @nx/angular:component navigation --standalone --project nba-ui 
>  NX  Generating @nx/angular:component
CREATE libs/nba-ui/src/lib/navigation/navigation.component.scss
CREATE libs/nba-ui/src/lib/navigation/navigation.component.html
CREATE libs/nba-ui/src/lib/navigation/navigation.component.spec.ts
CREATE libs/nba-ui/src/lib/navigation/navigation.component.ts
dany ~/Desktop/nba [main] $
```

Open the `navigation.component.html` file and insert the following template:

```xml
<nav>
  <a *ngFor="let navItem of navOptions">{{navItem}}</a>
</nav>
```

To make the desired changes, open up your `` `navigation.component.ts` `` file and add this friendly code snippet:

```typescript
import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'nba-navigation',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './navigation.component.html',
  styleUrls: ['./navigation.component.scss'],
})
export class NavigationComponent {

  @Input() navOptions = [ 'home', 'about']
}
```

Edit the `navigation.component.scss` file and add the following CSS rule:

```typescript
nav {
  display: flex;
  gap: 1rem
}
```

Alright, we have the component ready! Now, let's ask NX to assist us in creating the stories for our component using Storybook.

Run the following command: `nx generate @nx/angular:stories --name=nba-ui`

```bash
nx generate @nx/angular:stories --name=nba-ui

>  NX  Generating @nx/angular:stories

✔ Do you want to generate Cypress specs as well? (y/N) · true
CREATE libs/nba-ui/src/lib/button/button.component.stories.ts
CREATE apps/nba-ui-e2e/src/e2e/button/button.component.cy.ts
dany ~/Desktop/nba [main] $ nx storybook nba-ui
```

Perfect! Let's run Storybook using the command `` `nx storybook nba-ui` `` and see the final results.

```bash
nx storybook nba-ui                            

> nx run nba-ui:storybook

info => Starting manager..
info Addon-docs: using MDX2
info => Using implicit CSS loaders
info => Using angular browser target options from "nba-ui:build-storybook"
info => Using angular project with "tsConfig:/Users/dany/Desktop/nba/libs/nba-ui/.storybook/tsconfig.json"
info => Using default Webpack5 setup
<i> [webpack-dev-middleware] wait until bundle finished
<i> [webpack-dev-middleware] wait until bundle finished: /apple-touch-icon-precomposed.png
╭────────────────────────────────────────────────╮
│                                                │
│   Storybook 7.1.0 for angular started          │
│   102 ms for manager and 8.36 s for preview    │
│                                                │
│    Local:            http://localhost:4400/    │
│    On your network:  http://localhost:4400/    │
│                                                │
╰────────────────────────────────────────────────╯
```


![all our projects](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yf17iwvg3d22n9mw3e28.png)

Yes, we have all our projects with ESLint, Prettier, Jest testing, Cypress, and Storybook without issues!

## Nx Commands

We learn how to create applications, libraries, generate components, or configure plugins we want to use.

We have a set of commands; let's show some more:

For example, if we want to lint our nba-ui library, run the command `nx run nba-ui:lint`

```bash
dany ~/Desktop/backup/nba [main] $ nx run nba-ui:lint
> nx run nba-ui:lint
Linting "nba-ui"...
All files pass linting.
 ———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
 >  NX   Successfully ran target lint for project nba-ui (962ms)
dany ~/Desktop/backup/nba [main] $
```

But what happens if you want to lint more than one project? We need to specify the `--target` task, in our case `'lint'`, and the `--projects.`

```bash
dany ~/Desktop/nba [main] $ nx run-many --target=lint --projects=nba-ui,nba-web 
 
    ✔  nx run nba-ui:lint (689ms)
    ✔  nx run nba-web:lint (715ms)

 —————————————————————————————————————————————————————————————————————————————————————————————

 >  NX   Successfully ran target lint for 2 projects (737ms)
```

Additionally, you can run the linter in all projects using the `--all flag.`

```bash
dany ~/Desktop/nba [main] $ nx run-many --target=lint --all                    
 
    ✔  nx run nba-ui:lint  [existing outputs match the cache, left as is]
    ✔  nx run nba-web:lint  [existing outputs match the cache, left as is]
    ✔  nx run nba-ui-e2e:lint (579ms)
    ✔  nx run nba-web-e2e:lint (586ms)

 —————————————————————————————————————————————————————————————————————————————————————————————

 >  NX   Successfully ran target lint for 4 projects (616ms)
 
   Nx read the output from the cache instead of running the command for 2 out of 4 tasks.d/my-lib
```

Did you notice the output of the previous command "existing output matches the cache, left as is"?

Nx uses the cache to speed up our tasks, but to bypass Nx cache, use the flag `--skip-nx-cache`.

```bash

   dany ~/Desktop/nba [main] $ nx run-many --target=lint --all --sky-nx-cache
 
    ✔  nx run nba-web-e2e:lint (611ms)
    ✔  nx run nba-ui:lint (736ms)
    ✔  nx run nba-web:lint (767ms)
    ✔  nx run nba-ui-e2e:lint (567ms)

 —————————————————————————————————————————————————————————————————————————————————————————————

 >  NX   Successfully ran target lint for 4 projects (1s)
 
         With additional flags:
           --sky-nx-cache=true
```

Lastly, nx offers a visual method to view project dependencies and their relationships.

For example, if we use the nba-ui library in the nba-web app, it creates a relationship. How can we visualize it?

Nx provides the `nx graph` command, which visually displays how the projects are related easily.


![escription](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z29urp78lnj2sihlqnok.png)

If you are interested in expanding your knowledge and skills with Nx, I highly recommend diving into the official documentation, as it offers a wealth of valuable information and insights. Additionally, consider checking out the following resources to further your understanding:

* [The Angular Developer's Nx Handbook](https://leanpub.com/the-angular-developers-nx-handbook) by Lars Gyrup Brink Nielsen – This comprehensive handbook serves as an excellent guide for Angular developers looking to harness the full potential of Nx in their projects.
    
* [Setting up Nx Mono-repo](https://www.youtube.com/watch?v=xsW2QPJ75so) by [Santosh](https://twitter.com/SantoshYadavDev) 🔥 by Santosh Yadav – great video provides step-by-step instructions on setting up an Nx mono-repo.
    

## Recap

We have discovered how to effortlessly and seamlessly set up most of the commonly used libraries in our Angular project by utilizing the powerful Nx tool. Furthermore, we get into the visualization of graph dependencies, which gave us a clear understanding of the relationships between various projects.

Also we show the capabilities of Nx, such as building, linting, and executing multiple or individual projects and using caching mechanisms, which significantly accelerates the completion of our routine tasks to improve your productivity.

In conclusion, we have covered various topics related to Nx and its numerous benefits for Angular developers. By leveraging the power of Nx, you can streamline your development process, improve collaboration, and ultimately create more efficient and robust applications.

* [Source code](https://github.com/danywalls/head-start-with-nx)