Deno - Angular Stack Proof of Concept
Tags: deno, angular
Published: 2020-05-28 06:45:27

---
series: Deno-Angular-PoC
---

The goal of this post is to give a step-by-step guide on how to set up a Proof of Concept (PoC) project using Deno and Angular. The PoC covers the following topics:
* Setting up a Deno server
* Generating an Angular application
* Serve the Angular application with Deno
* Call an endpoint of Deno from the Angular app

The result of this guide can be found on [GitHub](https://github.com/milantenk/angular-deno-stack-poc/tree/post_1).
The project can be easily used for playing around with this stack. In the following sections, I show how to set it up.

## Setting up the Deno server to serve the Angular app
* First of all, Deno has to be installed based on the [installation guide](https://deno.land/#installation). Please follow the installation instructions and when it is finished check the installation with running `deno run https://deno.land/std/examples/welcome.ts` from the command line. The result should be similar to this:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/zdrqkbnnxe5053j2gs3i.jpg)
* When it is successfully installed, create the project folder. In my case, it is `angular-deno-stack-poc`. In this folder a subfolder has to be created for the server, the folder name is `server`. 
* Let's open a Visual Studio Code in `angular-deno-stack-poc\server` folder and create a TypeScript file called `server.ts`.
* To download the `index.html` of the Angular app following code snippet is needed as first iteration: 
```javascript
import { Application, send } from "https://deno.land/x/oak/mod.ts";

const app = new Application();

app.use(async (context) => {
  await send(context, context.request.url.pathname, {
    root: `${Deno.cwd()}/../client-app/dist/angular-deno-poc`,
    index: "index.html",
  });
});

app.listen({ port: 8080 });
console.log(`Listening on localhost:${8080}`);
```
The above code uses `oak` middleware.
Details about it can be found in the [official documentation](https://oakserver.github.io/oak/). 

The above code snippet assumes that a built Angular application exists on `./../client-app/dist/angular-deno-poc` path. I describe in the next section how to create it. 

## Generate the Angular app
* Install [Node.js LTS](https://nodejs.org/en/) if it is not installed yet on the computer.
* If the Angular CLI is not installed globally yet install it with running `npm install -g @angular/cli` in the command line. If we type `ng --version` in the command line and the version is printed out then the installation was successful.
* In the terminal let's go back to the `angular-deno-stack-poc` folder and run
`ng new angular-deno-poc`. The Angular CLI asks some questions, I choose to use routing and use scss.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/10x7c5nr5ntpeih7oqaa.jpg)
* Rename the created folder to `client-app`. This way the Angular app is named `angular-deno-poc` in the development environment and it is located in the `client-app` folder.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/xw9mkntp754ytzp5pgrs.jpg)
* Navigate in terminal in the `client-app` folder and run `npm run build -- --prod`. This way a production build is created in the `dist` folder. If the build was successful the terminal shows the following output:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/a42x0ckorrl4n4iz7id3.jpg)
The app is ready, let's check if it can be served with the Deno server.

## Check the app in the browser
* Navigate in command line in `angular-deno-stack-poc\server` and run ` deno run --allow-net --allow-read .\server.ts` command. The server will listen on port 8080.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/s9nhbtedf0cx5tdjj75u.jpg)
* Open a browser and navigate to `http://localhost:8080/`. If every step was successful, the boilerplate code of Angular CLI is displayed.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ry3tndkunqkpky595lnz.jpg)

Now we have a running Deno server that serves the Angular app. As the next step, an endpoint is created and the Angular app will fetch some data from there.

## Add an endpoint to the server and fetch data from Angular
We are going to send a message string and a timestamp from the server to the client.
### Create a Data Transfer Object
* First a Data Transfer Object (Dto) is created, which describes the traveling data between the client and the server-side. As we have TypeScript on both sides of the stack, we can use the same TypeScript file for this. Let's create a new folder in `angular-deno-stack-poc` root folder, it should be called `common`.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/1c5x3b63bwqcmvguoz13.jpg)
* In the common folder the `message-dto.ts` file has to be created with the following content:

```javascript
export interface MessageDto {
    message: string;
    timeStamp: string;
}
```
### Create the endpoint
* As the next step the server code has to import the file created above and the endpoint has to be created. It means, that after update the server code has to look like this:

```javascript
import { Application, send, Router } from "https://deno.land/x/oak/mod.ts";
import { MessageDto } from "./../common/message-dto.ts";

const app = new Application();
const router = new Router();

router
  .get("/api/message", (ctx) => {
    const message: MessageDto = {message: "Hello from API!", timeStamp: new Date().toTimeString()}
    ctx.response.body = message;
  });

app.use(router.routes());
app.use(router.allowedMethods());
app.use(async (context) => {
  await send(context, context.request.url.pathname, {
    root: `${Deno.cwd()}/../client-app/dist/angular-deno-poc`,
    index: "index.html",
  });
});

app.listen({ port: 8080 });
console.log(`Listening on localhost:${8080}`);
```
* After the code modification resart the Deno server.

* The endpoint sends response to get requests on `/api/message` route. It can be check from the browser with navigating to `http://localhost:8080/api/message` url. 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/97fcnswixoas1kzxbohq.jpg)

### Add a service to Angular
To fetch data from the server an Angular service has to be used.
* In `angular-deno-stack-poc\client-app\src\app` create the `core` folder and create a file called `example.service.ts`. The content of it should be the following:

```javascript
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { MessageDto } from '../../../../common/message-dto'


@Injectable()
export class ExampleService {

    constructor(private http: HttpClient) { }

    getExampleMessage(): Observable<MessageDto> {
        return this.http.get<MessageDto>('/api/message');
    }
}
```
* In `app.module.ts` import the `HttpClientModule` and add `ExampleService` to the providers. The content of the file should be following:

```javascript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
import { ExampleService } from './core/example.service';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [ExampleService],
  bootstrap: [AppComponent]
})
export class AppModule { }
```
* To display the fetched data change `app.component.ts` content to the below snippet:

```javascript
import { Component } from '@angular/core';
import { ExampleService } from './core/example.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  message: string;
  timeStamp: string;

  constructor(private exampleService: ExampleService) { }
  ngOnInit() {
    this.exampleService.getExampleMessage().subscribe((result) => {
      this.message = result.message;
      this.timeStamp = result.timeStamp;
    });
  }
}
```

And change `app.component.html` to

```html
<h3>Message from the server API:</h3>
<p>{{message}}</p>
<p>{{timeStamp}}</p>
```
* After the changes, the Angular app has to be rebuilt. Run `npm run build -- --prod` from the `angular-deno-stack-poc\client-app` in command line.
* After that if the `http://localhost:8080/` url is checked in the browser the fetched data is displayed:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/y3t03fsaus0bgmla8n48.jpg)

## Conclusion
It was quite easy to get started with Deno. I find it very convenient that it supports TypeScript out of the box. Having the same programming language on frontend and backend side has several benefits, for example in my PoC, I was able to use the same Dto to represent the transferred object. 

It would be great to use the same input validation code on frontend and backend side. Do you have any tips or best practices for that? Please let me know. :)

There is a post that continues this topic with setting up the [development tools](https://dev.to/milantenk/deno-angular-development-environment-3ef1) on this stack.