5 Min. Lesezeit

Deno vs. Node - a comparison by example

new technology
Miniatur-Dinosaurierfigur auf einer grob texturierten Baumrinde in natürlichem Licht.

Deno is the new kid on the block: A simple, small and secure runtime built to run JavaScript and TypeScript. With this functionality it directly competes with Node.js.

What it's all about

Denois a simple, small and secure runtime for JavaScript and TypeScript originally developed by Ryan Dahl - the creator of Node.js. In contrast to Node.js Deno "explicitly takes on the role of both runtime and package manager within a single executable". Watch Ryan Dahl announcing Deno at JSConf back in 2018: 10 Things I regret about Node.js

Node.json the other side is perhaps the most popular serverside JavaScript runtime environment originally developed by - again - Ryan Dahl.

So let's get into detail and compare those runtimes.

As always all code-samples are available in our public Github repo.

Install

As I am working mostly on mac OS I will cover mac OS aspects only - please refer to the platform docs for support of other operating systems.

Deno
brew install deno

That's it - brew installs deno on your system.

Over time you might run into the requirement to change different versions of deno on your system. For that there is dvm - the deno version manager. This small but very useful tool enables you to simply switch versions:

dvm install 1.0.0
dvm install 1.23.3
dvm use 1.23.3
Node.js
brew install nodejs

Just to be fair - the same support is given for Node.js.

As for deno there is a comparable feature available for Node.js (which of course is the older feature ;)

nvm use latest
nvm install 14
nvm use 14
Getting started

Let's go into the code - and beyond the classic Hello world. Both runtimes are best used for writing servers. So let's just do that.

deno

Deno shines in a new security concept: As a developer you need to explicitly grant access to resources such as network, file access, etc. Let's see how this works by access a simple web API:

Typescriptfetch-deno.ts\n\nconst url = 'http://hn.algolia.com/api/v1/search?query=typescript';\n \nfetch(url)\n  .then((result) => result.json())\n  .then((result) => console.log(result.hits));

So when you try to run this code with

deno run fetch-deno.ts

you should see the following error in your terminal:

Deno denies per default network access - which is a great security improvement. When you type

deno run --allow-net fetch-deno.ts

everything works fine and you should see a JSON list of 20 items.

A second thing is interesting in this short code sample:

Deno provides the same interface as the Browser API. This means that apps written for the Browser can be executed directly in Deno.

Let's digg a bit deeper and write a simple HTTP server in Deno.

deno-server.ts\n\nimport { serve } from \"https://deno.land/std@0.149.0/http/server.ts\";\n\nfunction handler(req: Request): Response {\n    return new Response(\"Hello, World!\");\n  }\n\nserve(handler);

This code unveils another unique feature of Deno:

Deno imports all external libraries with an absolute path. The code is loaded directly via URLs. This is a big difference to Node.js: You do not need to run npm install or anything comparable. Deno is loading the external code libraries for the first run and caches it - a concept inspired by the Go language.

Node.js

To be fair we need to compare the Node.js runtime by executing the same code as in deno.

So let's start with a simple fetch:

fetch-node.ts\n\nlet url = 'http://hn.algolia.com/api/v1/search?query=typescript';\n \nfetch(url)\n  .then((result) => result.json())\n  .then((result) => console.log(result.hits));

As this code is using a new feature you need to ensure that you are running on the latest Node.js version (as of writing this article it was 18.7.0).

When you now run:

node fetch-node.ts

you should see again a JSON list containing 20 items.

Writing a simple HTTP server in Node.js is rather straight forward.

nodejs-server.ts\n\nconst http = require('http');\n\nconst hostname = '127.0.0.1';\nconst port = 3000;\n\nconst server = http.createServer((req, res) => {\n  res.statusCode = 200;\n  res.setHeader('Content-Type', 'text/plain');\n  res.end('Hello World');\n});\n\nserver.listen(port, hostname, () => {\n  console.log(`Server running at http://${hostname}:${port}/`);\n});
Wrap up

So when it comes to dev experience deno solves a couple of teething issues from node - for me the best feature is the way more lightweight dependency management. But Node.js still is the de-facto standard for backend-software running JavaScript or TypeScript - with a way larger ecosystem when it comes to hosting and deployment, framework support, etc.

So the best you can currently do is - with most new technologies - keep deno on your watchlist and maybe give it a try for small to midsize projects. It's fast, secure and provides a stellar dev-experience. For big projects I still recommend Node.js. For now. Let's recap in a couple of months ;)