DEV Community

ILshat Khamitov
ILshat Khamitov

Posted on • Edited on

Creating an empty Angular project and linking it to an existing server on NestJS

The application is created through the nx schematic for Angular.

The server address is set rigidly in the code, in the following posts the address will be transferred to the environment variables.

To run E2E tests, "Playwright" is used.

1. Install the necessary libraries and create an empty Angular application

Commands

# Install all need main dev-dependencies
npm install --save-dev @nx/angular@19.5.3

# Create Angular application
./node_modules/.bin/nx g @nx/angular:application --directory=apps/client --name=client --projectNameAndRootFormat=as-provided --style=scss --ssr=true --viewEncapsulation=None --addTailwind=true --e2eTestRunner=playwright --bundler=webpack
Enter fullscreen mode Exit fullscreen mode

Console output
$ npm install --save-dev @nx/angular@19.5.3

added 222 packages, removed 278 packages, changed 3 packages, and audited 2136 packages in 39s

292 packages are looking for funding
  run `npm fund` for details

14 vulnerabilities (4 moderate, 10 high)

To address issues that do not require attention, run:
  npm audit fix

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

$ ./node_modules/.bin/nx g @nx/angular:application --directory=apps/client --name=client --projectNameAndRootFormat=as-provided --style=scss --ssr=true --viewEncapsulation=None --addTailwind=true --e2eTestRunner=playwright --bundler=webpack

 NX  Generating @nx/angular:application

Fetching @nx/playwright...
UPDATE .gitignore
UPDATE .prettierignore
UPDATE package.json
UPDATE nx.json
CREATE apps/client/project.json
CREATE apps/client/src/index.html
CREATE apps/client/src/styles.scss
CREATE apps/client/tsconfig.app.json
CREATE apps/client/tsconfig.editor.json
CREATE apps/client/tsconfig.json
CREATE apps/client/public/favicon.ico
CREATE apps/client/src/app/app.component.scss
CREATE apps/client/src/app/app.component.html
CREATE apps/client/src/app/app.component.spec.ts
CREATE apps/client/src/app/app.component.ts
CREATE apps/client/src/app/app.config.ts
CREATE apps/client/src/app/app.routes.ts
CREATE apps/client/src/app/nx-welcome.component.ts
CREATE apps/client/src/main.ts
CREATE apps/client/tailwind.config.js
CREATE apps/client/.eslintrc.json
CREATE apps/client/jest.config.ts
CREATE apps/client/src/test-setup.ts
CREATE apps/client/tsconfig.spec.json
CREATE apps/client-e2e/project.json
CREATE apps/client-e2e/src/example.spec.ts
CREATE apps/client-e2e/playwright.config.ts
CREATE apps/client-e2e/tsconfig.json
CREATE apps/client-e2e/.eslintrc.json
UPDATE .vscode/extensions.json
CREATE apps/client/src/main.server.ts
CREATE apps/client/src/app/app.config.server.ts
CREATE apps/client/tsconfig.server.json
CREATE apps/client/server.ts
npm WARN deprecated abab@2.0.6: Use your platform's native atob() and btoa() methods instead
npm WARN deprecated domexception@4.0.0: Use your platform's native DOMException instead

added 364 packages, removed 57 packages, changed 10 packages, and audited 2443 packages in 24s

297 packages are looking for funding
  run `npm fund` for details

12 vulnerabilities (2 moderate, 10 high)

To address issues that do not require attention, run:
  npm audit fix

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

 NX   👀 View Details of client

Run "nx show project client" to view details about this project.

Enter fullscreen mode Exit fullscreen mode

3. We are launching the build of all projects

Commands

# Build all applications and library
npm run build
Enter fullscreen mode Exit fullscreen mode

Console output
$ npm run build

> @nestjs-mod-fullstack/source@0.0.0 build
> npm run generate && npm run tsc:lint && ./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=build --skip-nx-cache=true


> @nestjs-mod-fullstack/source@0.0.0 generate
> ./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=generate --skip-nx-cache=true && npm run make-ts-list && npm run lint:fix

 NX   Successfully ran target generate for 0 projects (37ms)


> @nestjs-mod-fullstack/source@0.0.0 make-ts-list
> ./node_modules/.bin/rucken make-ts-list


> @nestjs-mod-fullstack/source@0.0.0 lint:fix
> npm run tsc:lint && ./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=lint --fix


> @nestjs-mod-fullstack/source@0.0.0 tsc:lint
> ./node_modules/.bin/tsc --noEmit -p tsconfig.base.json

apps/client/src/test-setup.ts:1:1 - error TS2578: Unused '@ts-expect-error' directive.

1 // @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Found 1 error in apps/client/src/test-setup.ts:1
Enter fullscreen mode Exit fullscreen mode

3. We get the error "Unused '@ts-expect-error' directive." and solve it

Since nx contains many different templates for different frameworks, you can often find implicit errors that are not clear how to fix, to bypass the current error, just simply interrupt the typing and delete the directive.

Updated file apps/client/src/test-setup.ts

(globalThis as any).ngJest = {
  testEnvironmentOptions: {
    errorOnUnknownElements: true,
    errorOnUnknownProperties: true,
  },
};
import 'jest-preset-angular/setup-jest';
Enter fullscreen mode Exit fullscreen mode

4. Re-launching the build of all projects

Commands

# Build all applications and library
npm run build
Enter fullscreen mode Exit fullscreen mode

Console output
$ npm run build

> @nestjs-mod-fullstack/source@0.0.0 build
> npm run generate && npm run tsc:lint && ./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=build --skip-nx-cache=true


> @nestjs-mod-fullstack/source@0.0.0 generate
> ./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=generate --skip-nx-cache=true && npm run make-ts-list && npm run lint:fix

 NX   Successfully ran target generate for 0 projects (25ms)


> @nestjs-mod-fullstack/source@0.0.0 make-ts-list
> ./node_modules/.bin/rucken make-ts-list


> @nestjs-mod-fullstack/source@0.0.0 lint:fix
> npm run tsc:lint && ./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=lint --fix


> @nestjs-mod-fullstack/source@0.0.0 tsc:lint
> ./node_modules/.bin/tsc --noEmit -p tsconfig.base.json


   ✔  nx run server:lint  [existing outputs match the cache, left as is]
   ✔  nx run server-e2e:lint  [existing outputs match the cache, left as is]
   ✔  nx run client:lint (1s)

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

 NX   Successfully ran target lint for 3 projects (1s)

      With additional flags:
        --fix=true

Nx read the output from the cache instead of running the command for 2 out of 3 tasks.


> @nestjs-mod-fullstack/source@0.0.0 tsc:lint
> ./node_modules/.bin/tsc --noEmit -p tsconfig.base.json


   ✔  nx run server:build:production (3s)
   ✔  nx run client:build:production (15s)

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

 NX   Successfully ran target build for 2 projects (15s)

Enter fullscreen mode Exit fullscreen mode

5. Add a command to the pm2 configuration to launch the Angular application in watch mode

Updated PM2 configuration ecosystem.config.json

{
  "apps": [
    {
      "name": "server",
      "script": "node ./dist/apps/server/main.js",
      "node_args": "-r dotenv/config"
    },
    {
      "name": "client",
      "script": "./node_modules/.bin/nx serve client --host=0.0.0.0 --disable-host-check",
      "node_args": "-r dotenv/config"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

6. We launch all projects in watch mode via pm2

Commands

nm run pm2:start
Enter fullscreen mode Exit fullscreen mode

Console output
$ npm run pm2:start

> @nestjs-mod-fullstack/source@0.0.0 pm2:start
> ./node_modules/.bin/pm2 start ./ecosystem.config.json


>>>> In-memory PM2 is out-of-date, do:
>>>> $ pm2 update
In memory PM2 version: 3.1.3
Local PM2 version: 5.4.2

[PM2][WARN] Applications server, client not running, starting...
[PM2] App [server] launched (1 instances)
[PM2] App [client] launched (1 instances)
┌────┬───────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name      │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├────┼───────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 1  │ client    │ default     │ N/A     │ fork    │ 454827   │ 0s     │ 0    │ online    │ 0%       │ 13.2mb   │ endy     │ disabled │
│ 0  │ server    │ default     │ N/A     │ fork    │ 454826   │ 0s     │ 0    │ online    │ 0%       │ 25.6mb   │ endy     │ disabled │
└────┴───────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
Enter fullscreen mode Exit fullscreen mode

7. Running unit tests

Commands

npm run test
Enter fullscreen mode Exit fullscreen mode

Console output
$ npm run test

> @nestjs-mod-fullstack/source@0.0.0 test
> ./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=test --skip-nx-cache=true --passWithNoTests --output-style=stream-without-prefixes



> nx run client:test --passWithNoTests


> nx run server:test --passWithNoTests



 NX   Running target test for 2 projects

      With additional flags:
        --passWithNoTests=true

   ✔  nx run server:test (3s)

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

 NX   Running target test for 2 projects

      With additional flags:
        --passWithNoTests=true

   →  Executing 1/1 remaining tasks...
   ✔  nx run client:test (3s)

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

 NX   Successfully ran target test for 2 projects (3s)

      With additional flags:
        --passWithNoTests=true


 NX   Nx detected a flaky task

  server:test

Flaky tasks can disrupt your CI pipeline. Automatically retry them with Nx Cloud. Learn more at https://nx.dev/ci/features/flaky-tasks
Enter fullscreen mode Exit fullscreen mode

8. To run e2e tests on Angular, you need to install additional libraries

Commands

npx playwright install
Enter fullscreen mode Exit fullscreen mode

Console output
$ npx playwright install
Downloading Chromium 128.0.6613.18 (playwright build v1129) from https://playwright.azureedge.net/builds/chromium/1129/chromium-linux.zip
162.8 MiB [====================] 100% 0.0s
Chromium 128.0.6613.18 (playwright build v1129) downloaded to /home/endy/.cache/ms-playwright/chromium-1129
Downloading FFMPEG playwright build v1009 from https://playwright.azureedge.net/builds/ffmpeg/1009/ffmpeg-linux.zip
2.6 MiB [====================] 100% 0.0s
FFMPEG playwright build v1009 downloaded to /home/endy/.cache/ms-playwright/ffmpeg-1009
Downloading Firefox 128.0 (playwright build v1458) from https://playwright.azureedge.net/builds/firefox/1458/firefox-ubuntu-20.04.zip
85.6 MiB [====================] 100% 0.0s
Firefox 128.0 (playwright build v1458) downloaded to /home/endy/.cache/ms-playwright/firefox-1458
Downloading Webkit 18.0 (playwright build v2051) from https://playwright.azureedge.net/builds/webkit/2051/webkit-ubuntu-20.04.zip
134.5 MiB [====================] 100% 0.0s
Webkit 18.0 (playwright build v2051) downloaded to /home/endy/.cache/ms-playwright/webkit-2051
Enter fullscreen mode Exit fullscreen mode

9. Running e2e tests

Commands

./node_modules/.bin/nx runmany --exclude=@nestjs-mod-fullstack/source --all -t=e2e --skip-nx-cache=true --output-style=stream-without-prefixes
Enter fullscreen mode Exit fullscreen mode

Console output
$ ./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=e2e --skip-nx-cache=true --output-style=stream-without-prefixes


> nx run client-e2e:e2e

> playwright test

 NX   Running target e2e for 2 projects and 1 task they depend on


 NX   Running target e2e for 2 projects and 1 task they depend on

   →  Executing 1/3 remaining tasks...

   ⠇  nx run client-e2e:e2e
   ✔  nx run client-e2e:e2e (4s)

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


————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
   ✔  nx run server:build:production (2s)

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



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

 NX   Running target e2e for 2 projects and 1 task they depend on

   →  Executing 1/1 remaining tasks...

   ⠋  nx run server-e2e:e2e

   ✔  nx run server-e2e:e2e (2s)

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

 NX   Successfully ran target e2e for 2 projects and 1 task they depend on (8s)
Enter fullscreen mode Exit fullscreen mode

10. Adding work with http in the Angular application

Updated config apps/client/src/app/app.config.ts

import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { appRoutes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
import { provideHttpClient } from '@angular/common/http'; // <---

export const appConfig: ApplicationConfig = {
  providers: [
    provideClientHydration(),
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(appRoutes),
    provideHttpClient(), // <---
  ],
};
Enter fullscreen mode Exit fullscreen mode

11. Adding receiving data from the server and saving it to a local variable

Updated root typescript file apps/client/src/app/app.component.ts

import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { RouterModule } from '@angular/router';
import { NxWelcomeComponent } from './nx-welcome.component';
import { HttpClient } from '@angular/common/http';

@Component({
  standalone: true,
  imports: [NxWelcomeComponent, RouterModule],
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss',
  encapsulation: ViewEncapsulation.None,
})
export class AppComponent implements OnInit {
  title = 'client';
  serverMessage!: string;

  constructor(private readonly httpClient: HttpClient) {}

  ngOnInit() {
    this.httpClient.get<{ message: string }>('http://localhost:3000/api').subscribe((result) => (this.serverMessage = result.message));
  }
}
Enter fullscreen mode Exit fullscreen mode

12. Adding the display of receiving data from the server

Updated root html file apps/client/src/app/app.component.html

<app-nx-welcome></app-nx-welcome> <router-outlet></router-outlet>
<div id="serverMessage">{{ serverMessage }}</div>
Enter fullscreen mode Exit fullscreen mode

13. Updating the E2E test in which we check the receipt and display of data from the server

Updated test file apps/client-e2e/src/example.spec.ts

import { test, expect } from '@playwright/test';

test('has title', async ({ page }) => {
  await page.goto('/');

  // Expect h1 to contain a substring.
  expect(await page.locator('h1').innerText()).toContain('Welcome');
});

test('has serverMessage', async ({ page }) => {
  await page.goto('/');

  // Expect h1 to contain a substring.
  expect(await page.locator('#serverMessage').innerText()).toContain('Hello API');
});
Enter fullscreen mode Exit fullscreen mode

14. Re-running the e2e tests

Commands

./node_modules/.bin/nx runmany --exclude=@nestjs-mod-fullstack/source --all -t=e2e --skip-nx-cache=true --output-style=stream-without-prefixes
Enter fullscreen mode Exit fullscreen mode

Console output
$ ./node_modules/.bin/nx run-many --exclude=@nestjs-mod-fullstack/source --all -t=e2e --skip-nx-cache=true --output-style=stream-without-prefixes


> nx run client-e2e:e2e

> playwright test

 NX   Running target e2e for 2 projects and 1 task they depend on


 NX   Running target e2e for 2 projects and 1 task they depend on

   →  Executing 1/3 remaining tasks...

   ⠹  nx run client-e2e:e2e
   ✔  nx run client-e2e:e2e (5s)

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


————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
   ✔  nx run server:build:production (3s)

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



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

 NX   Running target e2e for 2 projects and 1 task they depend on

   →  Executing 1/1 remaining tasks...

   ⠦  nx run server-e2e:e2e

   ✔  nx run server-e2e:e2e (2s)

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

 NX   Successfully ran target e2e for 2 projects and 1 task they depend on (10s)
Enter fullscreen mode Exit fullscreen mode

15. Stopping pm2 projects

Commands

nm run pm2:stop
Enter fullscreen mode Exit fullscreen mode

Console output
$ npm run pm2:stop

> @nestjs-mod-fullstack/source@0.0.0 pm2:stop
> ./node_modules/.bin/pm2 delete all


>>>> In-memory PM2 is out-of-date, do:
>>>> $ pm2 update
In memory PM2 version: 3.1.3
Local PM2 version: 5.4.2

[PM2] Applying action deleteProcessId on app [all](ids: [ 0, 1 ])
[PM2] [server](0)[PM2] [client](1) ✓
┌────┬───────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name      │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
└────┴───────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
Enter fullscreen mode Exit fullscreen mode

There are no pictures in the post, the application is checked through tests, but if someone needs to see the result, the server's response can be received at: http://localhost:3000/api , and the client's response to the address: http://localhost:4200/

In the next post, I will add a docker image with the Postgres database and writing and running migrations via Flyaway...

Links

https://nestjs.com -the official website of the framework
https://nestjs-mod.com -the official website of additional utilities
https://github.com/nestjs-mod/nestjs-mod-fullstack -the project from the post
https://github.com/nestjs-mod/nestjs-mod-fullstack/commit/32bcd1171985f5bd22e10b67c6b179807ef75cfc - commit to current changes

Top comments (0)