What’s Deno, and how is it different from Node.js?

Prateek Singh
Webtips
Published in
10 min readJun 1, 2020

I explore new projects every week, and it’s rare that one grabs my attention as much as Deno did.

In this post I want to get you up to speed with Deno quickly. We’ll compare it with Node.js, and build your first REST API with it.

Table of contents

  • What is Deno
  • Why Deno?Why Now
  • Should you learn Deno?
  • Will it replace NodeJs?
  • First-class Typescript support
  • Similarities and differences with NodeJs
  • No package manager
  • Install Deno
  • The Deno Commands
  • Your First Deno App

What is Deno?

If you are familiar with Node.js, the popular server-side JavaScript ecosystem, then Deno is just like Node. Except deeply improved in many ways.

Let’s start from a quick list of the features I like the most about Deno:

  • It is based on modern features of the JavaScript language
  • It has an extensive standard library
  • It has TypeScript at its core, which brings a huge advantage in many different ways, including a first-class TypeScript support (you don’t have to separately compile TypeScript, it’s automatically done by Deno)
  • It embraces ES modules.
  • It has no package manager
  • It has a first-class await
  • It has a built-in testing facility
  • It aims to be browser-compatible as much as it can, for example by providing a built-in fetch and the global window object

We’ll explore all of those features in this guide.

After you use Deno and learn to appreciate its features, Node.js will look like something old.

Especially because the Node.js API is callback-based, as it was written way before promises and async/await. There’s no change available for that in Node, because such a change would be monumental. So we’re stuck with callbacks or with promisifying API calls.

Node.js is awesome and will continue to be the de facto standard in the JavaScript world. But I think we’ll gradually see Deno get adopted more and more because of its first-class TypeScript support and modern standard library.

Deno can afford to have everything written with modern technologies, since there’s no backward compatibility to maintain. Of course there’s no guarantee that in a decade the same will happen to Deno and a new technology will emerge, but this is the reality at the moment.

Why Deno? Why now?

Deno was announced almost 2 years ago by the original creator of Node.js, Ryan Dahl, at JSConf EU. Watch the YouTube video of the talk, it’s very interesting and it’s a mandatory watch if you are involved in Node.js and JavaScript in general.

Every project manager must make decisions. Ryan regretted some early decisions in Node. Also, technology evolves, and today JavaScript is a totally different language than what it was back in 2009 when Node started. Think about the modern ES6/2016/2017 features, and so on.

So he started a new project to create some sort of second wave of JavaScript-powered server side apps.

The reason I am writing this guide now and not back then is because technologies need a lot of time to mature. And we have finally reached Deno 1.0 (1.0 should be released on May 13, 2020), the first release of Deno officially declared stable.

That’s might seem to be just a number, but 1.0 means there will not be major breaking changes until Deno 2.0. This is a big deal when you dive into a new technology — you don’t want to learn something and then have it change too fast.

Should you learn Deno?

That’s a big question.

Learning something new such as Deno is a big effort. My suggestion is that if you are starting out now with server-side JS and you don’t know Node yet, and have never written any TypeScript, I’d start with Node.

No one was ever fired for choosing Node.js (paraphrasing a common quote).

But if you love TypeScript, don’t depend on a gazillion npm packages in your projects and you want to use await anywhere, hey Deno might be what you’re looking for.

Will it replace Node.js?

No. Node.js is a giant, well established, incredibly well-supported technology that is going to stay around for decades.

First-class TypeScript support

Deno is written in Rust and TypeScript, two of the languages that are really growing fast today.

In particular, being written in TypeScript means we get a lot of the benefits of TypeScript even if we might choose to write our code in plain JavaScript.

And running TypeScript code with Deno does not require a compilation step — Deno does that automatically for you.

You are not forced to write in TypeScript, but the fact the core of Deno is written in TypeScript is huge.

First, an increasingly large percentage of JavaScript programmers love TypeScript.

Second, the tools you use can infer many information about software written in TypeScript, like Deno.

This means that when we code in VS Code, for example (which of course has a tight integration with TypeScript since both are developed at Micro Soft), we can get benefits like type checking as we write our code, and advanced IntelliSense features. In other words the editor can help us in a deeply useful way.

Similarities and differences with Node.js

Since Deno is basically a Node.js replacement, it’s useful to compare the two directly.

Similarities:

  • Both are developed upon the V8 Chromium Engine
  • Both are great for developing server-side with JavaScript

Differences:

  • Node is written in C++ and JavaScript. Deno is written in Rust and TypeScript.
  • Node has an official package manager called npm. Deno does not, and instead lets you import any ES Module from URLs.
  • Node uses the CommonJS syntax for importing packages. Deno uses ES Modules, the official way.
  • Deno uses modern ECMAScript features in all its API and standard library, while Node.js uses a callbacks-based standard library and has no plans to upgrade it.
  • Deno offers a sandbox security layer through permissions. A program can only access the permissions set to the executable as flags by the user. A Node.js program can access anything the user can access.
  • Deno has for a long time envisioned the possibility of compiling a program into an executable that you can run without external dependencies, like Go, but it’s still not a thing yet. That’d be a game changer.

No package manager

Having no package manager and having to rely on URLs to host and import packages has pros and cons. I really like the pros: it’s very flexible, and we can create packages without publishing them on a repository like npm.

I think that some sort of package manager will emerge, but nothing official is out yet.

The Deno website provides code hosting (and thus distribution through URLs) to 3rd party packages: https://deno.land/x/

Install Deno

Enough talk! Let’s install Deno.

The easiest way is to use Homebrew:

brew install deno

Once this is done, you will have access to the deno command. Here’s the help that you can get using deno --help:

flavio@mbp~> deno --help
deno 0.42.0
A secure JavaScript and TypeScript runtime
Docs: https://deno.land/std/manual.md
Modules: https://deno.land/std/ https://deno.land/x/
Bugs: https://github.com/denoland/deno/issues
To start the REPL, supply no arguments:
deno
To execute a script:
deno run https://deno.land/std/examples/welcome.ts
deno https://deno.land/std/examples/welcome.ts
To evaluate code in the shell:
deno eval "console.log(30933 + 404)"
Run 'deno help run' for 'run'-specific flags.USAGE:
deno [OPTIONS] [SUBCOMMAND]
OPTIONS:
-h, --help
Prints help information
-L, --log-level <log-level>
Set log level [possible values: debug, info]
-q, --quiet
Suppress diagnostic output
By default, subcommands print human-readable diagnostic messages to stderr.
If the flag is set, restrict these messages to errors.
-V, --version
Prints version information
SUBCOMMANDS:
bundle Bundle module and dependencies into single file
cache Cache the dependencies
completions Generate shell completions
doc Show documentation for a module
eval Eval script
fmt Format source files
help Prints this message or the help of the given subcommand(s)
info Show info about cache or info related to source file
install Install script as an executable
repl Read Eval Print Loop
run Run a program given a filename or url to the module
test Run tests
types Print runtime TypeScript declarations
upgrade Upgrade deno executable to newest version
ENVIRONMENT VARIABLES:
DENO_DIR Set deno's base directory (defaults to $HOME/.deno)
DENO_INSTALL_ROOT Set deno install's output directory
(defaults to $HOME/.deno/bin)
NO_COLOR Set to disable color
HTTP_PROXY Proxy address for HTTP requests
(module downloads, fetch)
HTTPS_PROXY Same but for HTTPS

The Deno commands

Note the SUBCOMMANDS section in the help, that lists all the commands we can run. What subcommands do we have?

  • bundle bundle module and dependencies of a project into single file
  • cache cache the dependencies
  • completions generate shell completions
  • doc show documentation for a module
  • eval to evaluate a piece of code, e.g. deno eval "console.log(1 + 2)"
  • fmt a built-in code formatter (similar to gofmt in Go)
  • help prints this message or the help of the given subcommand(s)
  • info show info about cache or info related to source file
  • install install script as an executable
  • repl Read-Eval-Print-Loop (the default)
  • run run a program given a filename or url to the module
  • test run tests
  • types print runtime TypeScript declarations
  • upgrade upgrade deno to the newest version

You can run deno <subcommand> help to get specific additional documentation for the command, for example deno run --help.

As the help says, we can use this command to start a REPL (Read-Execute-Print-Loop) using deno without any other option.

This is the same as running deno repl.

A more common way you’ll use this command is to execute a Deno app contained in a TypeScript file.

You can run both TypeScript (.ts) files, or JavaScript (.js) files.

If you are unfamiliar with TypeScript, don’t worry: Deno is written in TypeScript, buf you can write your “client” applications in JavaScript.

Here is a video that helps you understand typescript: TypeScript tutorial

Your first Deno app

Let’s run a Deno app for the first time.

What I find pretty amazing is that you don’t even have to write a single line — you can run a command from any URL.

Deno downloads the program, compiles it and then runs it:

Of course running arbitrary code from the Internet is not a practice I’d generally recommend. In this case we are running it from the Deno official site, plus Deno has a sandbox that prevents programs to do anything you don’t want to allow. More on this later.

This program is very simple, just a console.log() call:

console.log('Welcome to Deno 🦕')

If you open the https://deno.land/std/examples/welcome.ts URL with the browser, you’ll see this page:

Weird, right? You’d probably expect a TypeScript file, but instead we have a web page. The reason is the Web server of the Deno website knows you’re using a browser and serves you a more user friendly page.

Download the same UR using wget for example, which requests the text/plain version of it instead of text/html:

If you want to run the program again, it’s now cached by Deno and it does not need to download it again:

You can force a reload of the original source with the --reload flag:

deno run has lots of different options that were not listed in the deno --help. Instead, you need to run deno run --help to reveal them:

flavio@mbp~> deno run --help
deno-run
Run a program given a filename or url to the module.
By default all programs are run in sandbox without access to disk, network or
ability to spawn subprocesses.
deno run https://deno.land/std/examples/welcome.ts
Grant all permissions:
deno run -A https://deno.land/std/http/file_server.ts
Grant permission to read from disk and listen to network:
deno run --allow-read --allow-net https://deno.land/std/http/file_server.ts
Grant permission to read whitelisted files from disk:
deno run --allow-read=/etc https://deno.land/std/http/file_server.ts
USAGE:
deno run [OPTIONS] <SCRIPT_ARG>...
OPTIONS:
-A, --allow-all
Allow all permissions
--allow-env
Allow environment access
--allow-hrtime
Allow high resolution time measurement
--allow-net=<allow-net>
Allow network access
--allow-plugin
Allow loading plugins
--allow-read=<allow-read>
Allow file system read access
--allow-run
Allow running subprocesses
--allow-write=<allow-write>
Allow file system write access
--cached-only
Require that remote dependencies are already cached
--cert <FILE>
Load certificate authority from PEM encoded file
-c, --config <FILE>
Load tsconfig.json configuration file
-h, --help
Prints help information
--importmap <FILE>
UNSTABLE:
Load import map file
Docs: https://deno.land/std/manual.md#import-maps
Specification: https://wicg.github.io/import-maps/
Examples: https://github.com/WICG/import-maps#the-import-map
--inspect=<HOST:PORT>
activate inspector on host:port (default: 127.0.0.1:9229)
--inspect-brk=<HOST:PORT>
activate inspector on host:port and break at start of user script
--lock <FILE>
Check the specified lock file
--lock-write
Write lock file. Use with --lock.
-L, --log-level <log-level>
Set log level [possible values: debug, info]
--no-remote
Do not resolve remote modules
-q, --quiet
Suppress diagnostic output
By default, subcommands print human-readable diagnostic messages to stderr.
If the flag is set, restrict these messages to errors.
-r, --reload=<CACHE_BLACKLIST>
Reload source code cache (recompile TypeScript)
--reload
Reload everything
--reload=https://deno.land/std
Reload only standard modules
--reload=https://deno.land/std/fs/utils.ts,https://deno.land/std/fmt/colors.ts
Reloads specific modules
--seed <NUMBER>
Seed Math.random()
--unstable
Enable unstable APIs
--v8-flags=<v8-flags>
Set V8 command line options. For help: --v8-flags=--help
ARGS:
<SCRIPT_ARG>...
script args

--

--

Prateek Singh
Webtips
Writer for

Software Engineer at TTN | JS | REACT | HTML| CSS