Is Deno better than Node.js?

The Deno runtime for JavaScript and TypeScript is created on Rust and the V8 JavaScript engine, equivalent to Node.js.

Developed by Ryan Dahl, Node.js' original creator, it is designed to correct errors he made when he first envisioned and unleashed Node.js in 2009.

To recapitulate, he was dissatisfied with the lack of security, the lack of module resolution through node_modules, and the differing behaviour of the browser, among other things, which provoked him to implement Deno.

Both Node.js and Deno perform similar objectives. Each is based on V8, Google's runtime engine, and performs well with JavaScript server development.

At the moment, Node.js is a widely used technology, while Deno is a fairly new technology, and some of its attributes are still being developed.

The long-term goal could be to have an alternative to Node.js, so Deno cannot substitute Node.js instantly. In this article we will evaluate why Deno is better than Node.js:

  1. What is Deno?
  2. Little bit about Node.js
  3. Deno vs Node.js
  4. Deno: First-class TypeScript Support
  5. Deno: Permissions
  6. Deno: Browser Compatible
  7. Deno: Package Manager
  8. Deno: Standard Library

What is Deno?

With Deno, JavaScript and TypeScript run in a secure environment that supports WebAssembly, JavaScript XML (JSX), and its TypeScript extension, TSX.

In design by the creator of Node.js, Deno uses JavaScript and TypeScript compiler advances from 2009 to reimagine Node.

Deno
Deno

A similar approach to Node.js is taken by Deno, a JavaScript engine based on Google V8. TypeScript compiler is included in its executable image, unlike Node.

In Dahl's view, Node.js has three major problems: an inadequately developed module system based on centralized distribution; a number of legacy APIs that need to be supported; and a lack of security. Each of these problems is solved by Deno.

Deno Installation

Use one of the below command to install deno.

// Using Shell (macOS and Linux):
curl -fsSL https://deno.land/x/install/install.sh | sh

// Using Linux terminal
sudo snap install deno

// Using PowerShell (Windows):
irm https://deno.land/install.ps1 | iex

// Using Scoop (Windows):
scoop install deno

// Using Chocolatey (Windows):
choco install deno

// Using Homebrew (macOS):
brew install deno

// Using Nix (macOS and Linux):
nix-shell -p deno

// Build and install from source using Cargo:
cargo install deno --locked

Ensure the installation of deno by checking its version.

deno --version

Here is a sample code on typescript to print "Hello Deno" and check whether it works.

function hello(str: string) {
  return `Hello ${str}!`;
}
 
console.log(hello("Deno"));

To run the file index.ts enter the below command:

deno run <filename>

// example
deno run index.ts

Little bit about Node.js

In 2009, Ryan Dahl created Node.js, which handles asynchronous requests to the web server. As an example, Node.js will handle opening files by passing them to the file system and getting back to work immediately.

Servers simply return responses (in this case the contents of the file) to clients after the file system processes previous requests. Thus, Node.js involves less memory usage and can process requests more quickly.

Node.js
Node.js

In addition to collecting form data, generating dynamic page content, and performing all file operations like open, close, read, write, and delete on the server, and adding, deleting, or updating database data, Node.js is also able to collect form data, generate dynamic pages.

A better version of Node.js, Deno, was created by the same person - Ryan Dahl - and is said to take care of Node.js' deficiencies. It enhances the security of JavaScript runtime environments.

A change in JavaScript, particularly the TypeScript compiler, led to the idea of replacing Node.js with Deno. Node.js supported the CommonJS instead of ES Modules in Deno.

Deno vs Node.js

In the world of JavaScript, there are two major players: Node.js and Deno. Both have their pros and cons, but which one is the better option for you?

Features Deno Node.js
Languages Deno supports both JavaScript and TypeScript Node.js supports only JavaScript
Security Deno offers great security by running all the code in sandbox that prevents access to the file system. Node.js gives full access since it does not run the code in a sandbox and does not need permission to read or write in the file system.
TypeScript Support Deno offers out-of-the-box support for TypeScript. Node.js does not offer out-of-the-box support for TypeScript.
Code Engine V8 JavaScript V8 JavaScript
Package Manager URLs are used instead of a centralized registry like npm for importing modules in Deno. Despite being risky because of the unpredictable nature of the web, Deno tries to reduce this problem through caching. In Node.js, modules are imported via the Node Package Manager, or npm. Despite its convenience, npm has recently encountered some problems.

Deno: First-class TypeScript Support

The TypeScript language extends JavaScript by enabling customers to provide type data. By using a TypeScript compiler with caching techniques, Deno comes with TypeScript out of the box.

JavaScript is used to encrypt Node.js packages. Despite not having first-class typescript assistance, Node.js extensively uses popular typescript.

There are some TypeScript compiler options that Deno does not support. Documentation for Deno provides a comprehensive list of available options and their default values. The following is a sample Deno configuration file:

{
  "compilerOptions": {
    "allowJs": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "inlineSourceMap": true,
    "isolatedModules": true,
    "jsx": "react",
    "lib": ["deno.window"],
    "module": "esnext",
    "strict": true,
    "target": "esnext",
    "useDefineForClassFields": true
  }
}

Deno: Permissions

In addition to supporting JavaScript and TypeScript, Deno is known for its secure runtimes. The permissions system plays a part in maintaining security.

Here is a demonstration of how permission works in Deno:

async function getStatusCode() {
  try {
    const response = await fetch("https://www.myshop.com/");
    console.log(response.status);
  } catch (err) {
    console.error(err);
  }
}
 
getStatusCode();

You would receive the following permission error when you try to run the above script.

The above error message indicates that you haven't granted the network access. To grant the access type y in the terminal.

A flag can be used to permit filesystem access to one specific directory, for example --allow-net. In this way, administrators and users are authorised to prohibit access to programs to the minimum level that is crucial.

Deno allows the following permissions list:

  1. --allow-env=<allow-env> - allows all environment access like getting and setting of environment variables.
  2. --allow-hrtime - measures time with high resolution.
  3. --allow-net=<allow-net> - allows network access.
  4. --allow-ffi - allows you to load dynamic libraries, it does not has the same security reason like others since it does not run in sandbox. Use with caution because it an unstable feature.
  5. --allow-read=<allow-read> - Read access to the file system is allowed. To provide an allow-list of files and directories you can specify a comma-separated list.
  6. --allow-run=<allow-run> - Running subprocesses is allowed. The Deno 1.9 release adds the ability to specify an optional, comma-separated list of subprocesses to be allowed. In contrast to the Deno process, subprocesses are not run in a sandbox and therefore have fewer security restrictions.
  7. --allow-write=<allow-write> - Write access to the file system is allowed. To provide an allow-list of permitted file system access, you can specify a comma-separated list of directories or files.
  8. -A, --allow-all - Allow all permissions. This enables all security sensitive functions. Use with caution.

Deno: Browser Compatible

The browser compatibility makes it easy for developers to build applications that can be run in both the browser and Deno.

As much as possible, Deno will use web platform APIs (such as fetch) instead of introducing proprietary APIs wherever possible. Chrome and Firefox implement these APIs in accordance with the specifications. Because Deno has a different security model than the spec, it makes sense to deviate a bit from it.

Deno implements the following web platform APIs:

i.) fetch API

The fetch API provides an interface which allows you to make HTTP requests to servers from web browsers.

It requires only one parameter, the URL of the resource that you want to fetch.

let response = fetch(url);

To handle the response, you can use then() and catch() methods.

fetch(url)
    .then(response => {
        // handle the response
    })
    .catch(error => {
        // handle the error
    });

Example:

async function fetchText() {
    let response = await fetch('https://www.myshop.com');

    console.log(response.status); // 200
    console.log(response.statusText); // OK

    if (response.status === 200) {
        let data = await response.text();
        // handle data
    }
}

fetchText();

ii.) Web Worker API

In web applications, Web Workers enable script execution in a background thread separate from the main execution thread.

const worker = new Worker('/my-worker.js');
	worker.postMessage(['Message to worker']);
	worker.onmessage = (env) => {
  		console.log('data from worker', ev.data);
	};

iii.) CustomEvent, EventTarget and EventListener

Application events can be dispatched and listened to through the DOM Event API.

  1. EventTarget() - Creates new EventTarget  object instance.
  2. CustomEvent() - A CustomEvent interface represents events that are created by an application for a variety of purposes.
  3. addEventLister() - When an event is delivered to the target, the addEventListener() method of the EventTarget interface will call the specified function.

Example for custom events:

const events = require('events');

let emitter = new events.EventEmitter();

emitter.on('newEvent', (message)=>{
    console.log(`Message : ${message}`);
});

emitter.emit('newEvent', 'Atatus is one of the best performance monitoring tool');

Deno: Package Manager

The Node Package Manager (npm) is one of the most noteworthy parts of contemporary JavaScript development, regardless of whether you adore it or loathe it.

As a separate project from Node.js, npm might be included in Deno as well. However, Deno does not include it, nor does it mount packages from a node_modules directory.

CommonJS modules have long been favoured by Node.js because they predate the addition of native ES6 modules to JavaScript. A Deno module may be imported via an ES-style import and be used at an arbitrary remote URL.

As soon as you run your program in Deno, the module is downloaded and compiled instantly. A one-time download will then cache the results similarly to an npm install, so Deno programs will run offline after a one-time download.

import { path } from "https://deno.land/std@0.119.0/path/mod.ts";
import { http } from "https://deno.land/std@0.119.0/http/mod.ts";

As opposed to the centralized distribution of npm packages, this approach is preferred. Almost all Node.js programs are dependent on software available in the npm registry.

The lack of npm would prevent developers worldwide from obtaining their dependencies. According to Deno, modules can be hosted anywhere and arbitrary HTTP URIs can be considered "registries."

Is it necessary to always import by URL?

Deno has two options to avoid typing URLs everytime.

a.) Re-export the imported module

Import the modules in a local file as given below:

./deps.ts

export * as http from "https://deno.land/std@0.119.0/http/mod.ts";
export * as path from "https://deno.land/std@0.119.0/path/mod.ts";

And you can then import the dependencies from the ./deps.ts file.

./main.ts

import { path, http } from "./deps.ts";

b.) Create imports map

Specify the dependencies in a JSON file:

// import_map.json

{
   "imports": {
      "http/": "https://deno.land/std@0.119.0/http/mod.ts"
   }
}

And import them as such:

./main.ts

import { serve } from "http/server.ts";

By including the --importmap flag you can run the file:

deno run --importmap=import_map.json ./main.ts

Deno: Standard Library

Among Deno's features is a large standard library of modules evaluated by the core development team. There are no external dependencies on any of the modules in the standard library.

As a JavaScript runtime built on the V8 JavaScript engine, Deno has access to the V8 APIs. This enables Deno to support a standard library that is modeled after the Node.js standard library.

The Deno standard library provides a set of modules that are used for a variety of tasks, including:

  1. Making HTTP requests for Deno
  2. Working with the file system
  3. Prints formatted output with helpers.
  4. Tests and benchmarks your code using basic utilities.
  5. Helpers are included for handling XML, CSV, base64, YAML, and binary files.

In brief - Deno / Node.js?

The original Node.js developer has designed Deno as a JavaScript runtime from scratch. Despite the limitations of Node, this framework resolves many of them by abandoning centralized package management in favor of a entirely distributed model, adding fine-grained runtime permissions models, and integrating TypeScript.

It is possible that interest and adoption will grow now that Deno is actively adding enhanced Node.js compatibility.

In order to provide a viable transition pathway for existing projects, the Deno team is working toward full Node emulation. Its significance to the project is demonstrated by Deno's TypeScript-based standard library.

In spite of the fact that Node.js and TypeScript can be integrated easily, an intermediate build stage is required to convert TypeScript source code into JavaScript that can be executed by Node.

TypeScript is integrated from the beginning of Deno, reducing feedback loops and improving developer experiences.

The following infographic compares Deno and Node.js:

Deno vs Node.js

Monitor Your Node.js Applications with Atatus

Atatus keeps track of your Node.js application to give you a complete picture of your clients' end-user experience. You can determine the source of delayed response times, database queries, and other issues by identifying backend performance bottlenecks for each API request.

To make bug fixing easier, every Node.js error is captured with a full stack trace and the specific line of source code marked. To assist you in resolving the Node.js  error, look at the user activities, console logs, and all Node.js requests that occurred at the moment. Error and exception alerts can be sent by email, Slack, PagerDuty, or webhooks.

Try Atatus’s entire features free for 14 days.

Aarthi

Aarthi

Content Writer at Atatus.
Chennai

Monitor your entire software stack

Gain end-to-end visibility of every business transaction and see how each layer of your software stack affects your customer experience.