How to add Angular to a NestJs project ?
Other nestjs posts
I’ve made a few posts about NestJs, you can find them here:
Why ?
When I create a NestJs project, I often need to create a front end for it. I usually use Angular for that.
Usually I would create two distinct project, one for the NestJs back end, and one for the Angular front end. Each one with a different git repository.
Sometimes it makes sense to have two distinct project, but sometimes it’s not necessary. For example, if I want to create a small project that would be hosted on a single server, or to bundle it into a Docker image, it would be easier to have a single project.
So wanted to try a new approach, and create a NestJs project, and add an Angular project inside it.
Maybe it’s not the best approach, or maybe I won’t like it.
I will then apply this approach to my project called “MyBackups”.
The goal
First I want to have a single project, with a single git repository.
I want to be able to run both project in dev mode, with a single command.
In developpement mode want both application available on the same port, so it can be similar to the prod environment. Even if in local there is two port open with a proxy.
In production mode I want to run both project on the same port.
The final url will be http://myapp/
for the front and http://myapp/api
for the back.
Setting up the NestJs project
I create the new project with the NestJs CLI:
nest new project-name
Then I would configure the project as describe in a previous post.
I can now run the project with:
cd project-name
npm run start:dev
The app should be running on http://localhost:3000/
.
Creating the Angular project
In my cas I will put the Angular project in the client
folder, inside the NestJs project.
ng new client
Then I can run the front end with:
cd client
npm run start
The app should be running on http://localhost:4200/
.
Running both projects in dev mode
I could work like that, and start both project separately, but I would like to run both project in dev mode, with a single command.
I will use a package named concurrently to run both project in parallel.
npm i -D concurrently
Then I can add the following script to the package.json
file:
"start:dev": "concurrently \"npm run start:dev:server\" \"npm run start:dev:client\"",
"start:dev:server": "nest start --watch",
"start:dev:client": "cd client && npm run start"
Now If I run npm run start:dev
both project will start in parallel, and they will be available on http://localhost:4200/
, and http://localhost:3000/
.
Sending all api request to the back end
To proxy all http form the front end to the back end, I will use the proxy.conf.json
file.
{
"/api": {
"target": "http://localhost:3000",
"secure": false
}
}
Then I will add the proxy in the angular.json file:
{
"architect": {
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"browserTarget": "client:build:production"
},
"development": {
"browserTarget": "client:build:development",
"proxyConfig": "proxy.conf.json" // <--- HERE
}
}
}
}
}
On the nestjs part I will add a global prefix to all routes in main.ts
:
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.setGlobalPrefix('api');
await app.listen(3000);
}
bootstrap();
Now if I run npm run start:dev
the front end will be available on http://localhost:4200/
, and the back end on http://localhost:4200/api
.
I am now able to do the api call on /api
instead of http://localhost:3000
.
Deploying both projects
For the deployment I will use the (serve static module)[https://docs.nestjs.com/recipes/serve-static].
npm install --save @nestjs/serve-static
Then inside the app.module.ts
you can add the following import:
ServeStaticModule.forRoot({
rootPath: join(__dirname, '..','..', 'client/dist/client'),
}),
This tell nestjs to serve the files that are in the dist file of the front project. Theses files will be generated by the build command.
In development mode it won’t change anything.
Then to run the project in production we need to build both project and then run the nestjs server.
Here are all the commands:
nest build
cd client
ng build
cd ..
node dist/src/main
I created multiple scripts inside the package.json to simplify the process:
{
"scripts": {
"start:prod": "node dist/src/main",
"build": "npm run build:back && npm run build:client",
"build:back": "nest build",
"build:client": "cd client && npm run build",
}
}
Now we can run the production mode with:
npm run build
npm run start:prod
This example is available on github.