Deno - a Brand New Runtime For JavaScript and TypeScript That Aims to Replace Node JS

If you have been a Node JS developer like me, you now have something to be excited about. We have a new competitor in town - Deno. Deno is a simple, modern and secure runtime for JavaScript and TypeScript that uses V8 and is built in Rust.

How is Deno different from Node?

If you are a Node JS developer, you might be aware of its callback based architecture. Unfortunately callbacks are a thing of the past. We now have Promises. Deno supports Promises out of the box. Not only that it provides many more features -

  1. Out of the box TypeScript support. No more manual compiling.
  2. Top level await.
  3. Secure by default. A Deno app doesn't have access to filesystem, network or environment variables by default unless you allow them.
  4. No package manager like npm. No hassle of installing packages manually.
  5. Built in Has built-in utilities like a dependency inspector (deno info) and a code formatter (deno fmt).
  6. Deno aims to be browser compatible as much as possible. It provides a built-in fetch and global window object.

A Short History

Deno was announced in 2018 at the JSConf EU by Ryan Dahl, who is the original creator of Node JS (https://www.youtube.com/watch?v=M3BM9TB-8yA). According to him, there are many decisions he took that he dislikes about Node. Technology changes swiftly and over the years JS has changed a lot and so Ryan created Deno to take advantage of the improved features of JS.

The first stable release of Deno is Deno 1.0 which released on May 13, 2020.

Let's Dive Into Coding

Enough talk, let's get our hands dirty with Deno. First we will install Deno. It's just a single binary and installing it is as simple as running one command -

curl -fsSL https://deno.land/x/install/install.sh | sh

By default the binary is installed in $HOME/.deno/bin and so we need to add it to our $PATH. Add this line to your .bashrc or .zshrc

export PATH=$HOME/.deno/bin:$PATH

or if you're using fish like me, add this to your .config/fish/config.fish

set -gx $HOME/.deno/bin $PATH

Now we can get started with some real code.

We can run deno without any other options, or deno repl to start a REPL

Let's run your first app. One of the amazing features of Deno is that you can run apps straight from the url without even having to write a single line!

deno run https://deno.land/std/examples/welcome.ts

As you can see, Deno downloads the file from the URL and compiles and runs it. If you run the command again, it will not download the file again and will use the previously downloaded file.

Now let's run a more complex code. Create a file called first.ts and write the following code

import { serve } from "https://deno.land/std@0.50.0/http/server.ts";
const s = serve({ port: 8000 });
console.log("http://localhost:8000/");
for await (const req of s) {
  req.respond({ body: "Hello World\n" });
}

The first thing you should have noticed that we can import directly from the URL. There is no need to install a package. If you visit the URL in your browser, you'll see it is just a TypeScript file -

We are importing the serve function from this file -

We are assigning the port 8000 to the server and in the for loop we are responding to "Hello World" to each request. Observe that we can use await directly in the for loop without wrapping it inside any async function. It's because Deno has top level await.

Let's run this program.

deno run first.ts

As you can see, Deno downloads the file at the URL but it has its own dependencies and Deno downloads all of them and caches them.

Although we have an error

error: Uncaught PermissionDenied: network access to "0.0.0.0:8000", run again with the --allow-net flag
    at unwrapResponse ($deno$/ops/dispatch_json.ts:43:11)
    at Object.sendSync ($deno$/ops/dispatch_json.ts:72:10)
    at Object.listen ($deno$/ops/net.ts:51:10)
    at listen ($deno$/net.ts:152:22)
    at serve (https://deno.land/std@0.50.0/http/server.ts:261:20)
    at file:///home/aniket/deno/first.ts:2:11

This is because Deno runs in a sandbox by default and can't access the network unless the permission is explicitly granted with the --allow-net flag.

deno run --allow-net first.ts 

Now you should be able to visit localhost:8000 in your browser and see the response.

Further Reading

You can find more info about Deno in the official website. The docs are available at https://deno.land/manual/introduction and the standard library is available here

Aniket Bhattacharyea

Aniket Bhattacharyea