Node.js vs Deno: What You Need to Know

Node.js vs Deno: What You Need to Know

Deno vs Node

Since its announcement, Deno has generated quite a lot of interest within the JavaScript community. As a JavaScript runtime designed by the creator of Node, you might expect there to be be a lot of similarities between the two projects, and there are. However, there are also important differences, meaning you can’t just substitute one for the other.

This article will take a look at Deno in relation to its “older cousin” to help understand what they have in common, and what sets them apart. (If you want to get the skinny on Deno first, check out our recent introduction.)

Language Support

Both projects are JavaScript runtimes, allowing JavaScript code to be executed on a computer outside of a web browser. Let’s look at how they stack up in terms of language support.

Node.js

The current LTS release of Node (v12.18.1 as of writing) supports modern JavaScript syntax and features. It also supports about 75% of the ES2020 spec. ECMAScript modules are also supported, but are currently only classed as experimental: you need to use the .mjs file extension, or add the property "type": "module" to your project’s package.json file.

In order to run TypeScript (or any other language) on Node, the code needs to be compiled to JavaScript that the V8 engine can execute. There are several different ways to do this, with different pros and cons, so getting up and running means having to choose one of these and follow the necessary setup process.

Deno

I was unable to find any mention of the JavaScript spec supported by Deno, but as it also uses V8 under the hood I would assume a similar level of support as in Node. My own tests show that Deno supports ES2020 features like Promise.allSettled() and the globalThis keyword. ECMAScript modules are the default, with CommonJS modules not supported unless you use the Node compatibility library (more about this later).

TypeScript is supported as a first-class language in Deno, meaning that it works out-of-the-box: no installing additional tools to transpile to JavaScript first. Of course, the V8 engine doesn’t support TypeScript natively, so Deno is still transpiling the code under the hood, but this is all seamless and transparent to you as a developer.

I also couldn’t find mention of which version of TypeScript Deno v1.0.1 uses, but it supports optional chaining and nullish coalescing (but not private class fields) which would peg it as TS 3.7.

APIs

Deno and Node both expose their own APIs to developers, allowing us to write programs that can actually do useful things like read and write files, and send and receive network requests.

Node.js

When Node was first released, there was no built-in support for Promises. As a result of this, most of the APIs for asynchronous operations were written to take an error-first callback:

const fs = require('fs');
fs.readFile('readme.txt', (err, data) => {
  if (err) {
    // Handle the error
  }
  // Otherwise handle the data
});

Even though Node developers now have access to Promises and the async/await syntax, the APIs still expect callbacks in order to maintain backwards compatibility.

Deno

Deno’s API has been designed to take advantage of modern JavaScript features. All the asynchronous methods return Promises. Deno also supports top level await, meaning you can use await in your main script without having to wrap it in an async function.

try {
  const data = await Deno.readFile('readme.txt');
  // Handle the data
} catch (e) {
  // Handle the error
}

The development team also made the decision to use web standards where possible, which means they’ve implemented browser APIs where it’s practical to do so. Deno provides a global window object, and APIs such as addEventListener and fetch. Having access to fetch is particularly nice, as with Node you’d have to polyfill this or use a third-party library.

The compatibility module

Deno provides a compatibility layer with the aim of allowing you to reuse existing Node packages. It’s not yet complete, but it does currently support loading CommonJS modules via require(), among other things.

Package Management

Package management is one area where Deno represents a radical departure from Node’s way of doing things. As it’s still early days for Deno, it remains to be seen if its approach will prove to be advantageous.

Node.js

As you might be aware, Node comes with its own package manager called npm, which is used to install and manage third-party packages. npm is mainly used with the online npm registry, where most of the available third-party packages are listed.

When you use npm to install a package into your project, a package.json file is used to specify the package name and acceptable version range. The package itself (plus any packages it depends on) are then downloaded into a node_modules folder inside your project.

Deno

Deno does away with the need for a package manager altogether. Instead, packages are linked to directly via a URL:

import { Response } from "https://deno.land/std@0.53.0/http/server.ts";

On the first run of your code, Deno fetches and compiles all the dependencies. They are then cached on the file system, separately from your project, so subsequent runs are much faster.

Similar to npm’s package-lock.json file, Deno allows you to specify a lock file that will be used to ensure that only dependencies that match the exact version you originally imported will be used

Continue reading
Node.js vs Deno: What You Need to Know
on SitePoint.