Back to Deno

Deno is here. Have you explored it yet?

May 17, 2020
#deno
  
#react
  
#docker
  
#oak
  

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:

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

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

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

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:

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:

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.

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.

    "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?

todo-app-deno

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

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

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!

Anand Kumar
Manager at PublicisSapient
Back to Deno