Deno is here. Todo App(React) + Deno Server (API) + Docker.
Tags: deno, react, tutorial, typescript
Published: 2020-05-17 16:32:51

Hello Learners. I am sure you all are staying home and staying safe. Tough time but good opportunity to learn a lot. Be it due to different work style, life style or just getting more time due to cut down on commuting to work premises.

So, as we all heard that `Deno` is coming out and is created by the same guy who created much popular `Node`, **Ryan Dahl**. I was excited too and finally `1.0.0` came out.
And I started to have some hands on with it. Due to that very reason, I am writing this blog to document my experience.

I am not going to detail out on how to install `deno` or how to use the modules in details. They are available on official documentation page.

These are good to start with:

- _Manual_: https://deno.land/manual
- _v1.0.0_: https://deno.land/v1

In this post, I'll mention what I tried, what I liked about it and what I am planning to explore further. But, as technologies keeps evolving, these lists are not like finite.

Let's get started.

# What is Deno?
As per official documentation, **Deno** is a `secure` runtime for `JavaScript` and `TypeScript`.
It is like node but there are lot of enhancements done with it.
To summarize few:

- It has TypeScript at its core
- Features of Modern JavaScript
- No package manager
- Has first-class `await`
- Secure

I am pretty excited to get into it. Are you?

# Why Deno?
It was announced almost 2 years ago and Ryan Dahl mentioned some of the regrets he had with some early decisions in Node.

Here is the video for reference.

https://www.youtube.com/watch?v=M3BM9TB-8yA

So `Deno` is like second iteration of a server side apps powered by JavaScript.

Now, it is `v1.0.0` and officially stable, we can safely start using it as there won't be any breaking changes till we get to `v2.0.0`. :)

# What I built?
Okay, so here are the points that I wanted to cover/explore:

- **Server:** REST Api server built on `Deno`
- **Client:** A client application to consume those API
- **Docker:** Dockerise the complete working application

## Server:

I wanted to have a very basic REST API which can be used for CRUD operation. So, here is what I have decided to create for API:

|Route       |Method|Summary            |
|:-----------|:-----|:------------------|
|`/todos`    |GET   |List all todos     |
|`/todos/:id`|GET   |Get one todo by Id |
|`/todos`    |POST  |Create a todo      |
|`/todos/:id`|PUT   |Update a todo by Id|
|`/todos:/id`|DELETE|Delete a todo by Id|

Looks familiar from Node and express perspective, right?

The first thing, I wanted to have is something similar to `express` or `koa` that we use in `node`.

After some look around and documentation, I found something similar to `koa` for Deno and it is called `oak`. Below is the link to the module.

https://deno.land/x/oak/

Here is the basic server setup to get started:

> index.ts
```TypeScript
import { Application } from "./deps.ts";
import { HOST, PORT } from "./config.ts";

// Instantiate the application
const app = new Application();

const listenOptions = {
  port: Number(PORT),
};

console.log(`Listening on ${HOST}:${PORT}...`);

// start the server
await app.listen(listenOptions);

```

> deps.ts
```TypeScript
export {
  Application,
  Router,
  send,
  Context,
} from "https://deno.land/x/oak/mod.ts";
export { v4 } from "https://deno.land/std/uuid/mod.ts";
```

After basic server setup, here is how I have created the routes:

> routing.ts
```TypeScript
router
  .get("/todos", getTodos)
  .get("/todos/:id", getTodo)
  .post("/todos", addTodo)
  .put("/todos/:id", updateTodo)
  .delete("/todos/:id", deleteTodo);
```

I have imported this into `index.ts` and then added the route:
```TypeScript
import router from "./routing.ts";
...
app.use(router.routes());
...
```
At this point, I was able to complete and test my REST APIs and all were working fine.

Now, to serve the client page, I have added one more route into `index.ts` after `app.use(router.routes())` line as shown below:
```TypeScript
app.use(async (context: Context) => {
  await send(context, context.request.url.pathname, {
    root: `${Deno.cwd()}/public`,
    index: "index.html",
  });
});
```

The above route/code helped me to server my react app's `index.html` file from `public folder`

#### Running the Deno server
So, to run the server, we use `deno run ENTRY_POINT_FILE`. As we are ready to run the application, let me explain security part a bit.
In node, we don't specify whether the application can access the `environment` variables or can read/write file system or can access the network.

In Deno, these accesses are not provided by default due to sand-boxing. If required, we have to pass the arguments to our `deno run` command. The application that I worked on, below is the command to make it work properly.

```bash
deno run --allow-env --allow-net --allow-read --allow-write index.ts
```

You can see following arguments flag:
- `--allow-env`: To read environment variables in our codebase
- `--allow-net`: Helpful for networking
- `--allow-read`: Allows to read filesystem
- `--allow-write`: Allows to write to filesystem

More can be read on official documentation page.

### Good to know
- We can create a `dependency.ts` [deps.ts] to have all third-party modules at one place. This helps us to manage dependencies better. Any alternate way? Thoughts?

- In the `index.ts`, you can observe that the last line is using `await` without `async`. This is one of the feature of Deno where it has first-class `await`.

- Moreover, created some other files and introduced some middleware as per the `oak` setup.

- I have used simple `json` file to persist the data for REST API, so no Database. ;)


## Client
Nothing much here to be honest. I used `create-react-app` to scaffold a basic react application but in TypeScript. Used redux for statemanagement.

### Good to know:
- My deno application server was configured on different port than the client application. So, to make the api call, proxy was required. This can be easily achieved with `create-react-app` by doing a `proxy` entry into the `package.json`.

	```json
	"proxy": "http://localhost:4000"
	```

	> NOTE: This is for development purpose only

- Nothing fancy for client application and so I have used manual process to copy the build output into server's public folder. It wasn't the primary goal.

#### How client app looks?

![deno-todo-app](https://dev-to-uploads.s3.amazonaws.com/i/i3edr9x0nbu0w8irgtdv.png)

## Docker
To dockerise the app, I have created two files:

- Dockerfile
- docker-compose.yml

For, dockerfile, I have used `hayd/deno:alpine-1.0.0` image. This worked out of the box. Here is the sample file

```Docker
FROM hayd/deno:alpine-1.0.0

EXPOSE 4000

WORKDIR /app

USER deno

COPY deps.ts .
RUN deno cache deps.ts

COPY . .

RUN deno cache index.ts

CMD ["run", "--allow-net", "--allow-env", "--allow-read", "--allow-write", "index.ts"]
```
The above file's `CMD` might look bit strange but as explained above, we have to pass these arguments depending on the nature of application and sandbox feature of `Deno`.

And the `docker-compose.yml`
```yml
version: "3.7"

services:
  deno:
    image: "deno-todo:0.0.1"
    build: .
    ports:
      - "4000:4000"
    networks:
      - deno

networks:
    deno: {}

```

## What I liked about Deno
As we have seen how things progressed while I was trying out deno, here is what I liked:
- No package manager
- Once module is cached, the application starts really quick
- Sandboxing for better security
- ES6 support out of the box
- TypeScript

## Yet to explore
Okay, so as I mentioned, this is my first hands on with `Deno`  and there are lot to be explored but here are few things that I want to go into deeper:

- What would be the best way to manage the versioning of the third party modules.
- Server side rendering
- Hot reloading of deno server
- Creating own module for deno
- More on middlewares
- Creating own middlewares
- Authentication
- Using github action for the module and make it available on github to be used by others
- **and many more....**

There would be lot more to learn and explore but this is a starting point for me to take a next step. I am hoping that his will give you all some insight.

## Conclusion
In short, I liked Deno so far and this is something new and refreshing which keeps human being more motivated. I will try to keep up with it and will come up with more articles as time permits.

#### Source code is available on github.
https://github.com/elanandkumar/deno-todo-app

For now, Stay Home, Stay Safe and Keep Learning.

Happy Learning!