Deno vs nodeJs

Introduction

Both Deno and Nodejs are created by Ryan Dahl. It simply exists to run javascript outside of a browser among having other similarities. Then what is the need for Deno ? how did it come into existence ? Do we need to choose Deno over nodejs ? Let’s’ find out – 

Deno

Deno is a runtime for JavaScript and TypeScript based on Google’s v8 JavaScript engine for javascript and Typescript. It has been built using RUST. It is a secure environment which runs Typescript out of the box and ships the executable as a single file. Deno also includes a tester, formatter, linter, inspector, etc. Inshort, is a complete toolchain.

Deno is build with – 

  • Rust (Deno’s core was written in Rust, Node’s in C++)
  • Tokio (the event loop written in Rust)
  • TypeScript (Deno supports both JavaScript and TypeScript out of the box)
  • V8 (Google’s JavaScript runtime used in Chrome and Node, among others)

nodeJs

Node.js is a free, open-sourced, cross-platform JavaScript run-time environment that lets developers write command line tools and server-side scripts outside of a browser.

Node.js design shortcomings

According to Ryan Dahl, who revealed his regrets in Node.js (https://www.youtube.com/watch?v=M3BM9TB-8yA)  expressed the following shortcomings – 

  1. Not Sticking with PROMISES – promises were added to Node in June 2009 but removed them in February 2010 for minimal. It’s possible unified usage of promise in Node would have sped the delivery of the standardization and async/await.
  2. Security – V8 by itself is a very good security sandbox. But nodejs could have improved it further.
    Example : Your linter shouldn’t get complete access to your computer and network.
  3. The Build System (GYP): v8 used to use GYP before moving to GN. This leaves nodejs as the sole user of GYP. In Ryan Dhal’s own words – “The continued usage of GYP is the probably largest failure of Node core.Instead of guiding users to write C++ bindings to V8, I should have provided a core foreign function interface (FFI)”
  4. package.json  – Including npm in node distribution made it the defacto standard. This gave rise to the concept of a “module” as a directory of files. Some of these modules are even privately owned.
  5. Node_modules: It massively complicates the module resolution algorithm. Deviates greatly from browser semantics.
  6. require(“module”) without the extension “.js”  – Needless to say it’s not explicit. This is not how the browser javascript works. We cannot omit the “.js” in a script tag src attribute.The module loader has to query the file system at multiple locations trying to guess what the user intended.
  7. Index.js – Needlessly complicated the module loading system. Especially unnecessary after require supported package.json

Deno

  1. Security – By default a script should run without any network or file system write access.Users can opt in to access via flags: ` — allow-net` ` — allow-write` Doesn’t allow arbitrary native functions to be bound into V8.
  2. TypeScript compiler built into the executable : Typescript is a practical optionally typed language. It allows the code to grow seamlessly from quick hacks to large, well structured machinery.
  3. Simplified the module system: It is not compatible with node_modules. Imports are relative or absolute URLs ONLY, and in addition – they must provide an extension.Remote URLs fetched and cached indefinitely on the first load. And Vendoring can be done by specifying a not-default cache dir.
  4. Other important benefits – 
    1. Ships only a single executable with minimal linkage.
    2. Always die immediately on unhandled promises.
    3. Support top-level await.

Deep Dive

Security Aspect

To write a simple file in Nodejs we would typically use the fs package this way –

NodeJs

To run  this you would simply say assuming the file name is test.js- 

node test.js

As compared to deno – 

deno

Assuming the filename is test.ts, you would run this as – 

deno run test.ts

Now, we would straight away be prompted  – 

Deno requests write access to “/Users/user/folder/hello.txt”. Grant? [a/y/n/d (a = allow always, y = allow once, n = deny once, d = deny always)]

Let’s say you want to suppress these security concerns. Then we can choose to use the following flags as well – 

  1. –allow-write
  2. –allow-net
  3. –allow-env
  4. –allow-run

Modules
In nodejs, you would need to specify a package.json this way –

And do a 

npm install

Which would give rise to the folder node_modules this way –

And then we could just use them by requiring them this way –

See the absence of an extension in the “require” being allowed.

Deno, just like browsers, loads modules by URLs. 

by using URLs, Deno packages can be distributed without a centralized registry such as npm. What happens if the centralized repository goes down in nodejs ?

By importing code via URL, we make it possible for package creators to host their code wherever they see fit — decentralization at its finest. No more package.json and node_modules.

But what happens if the website having the dependency goes down for deno ?Deno caches the downloaded modules. Since the cache is stored on our local disk, the creators of Deno recommend checking it in our version control system (i.e., git) and keeping it in the repository. This way, even when the website goes down, all the developers retain access to the downloaded version.

So the final call …

Why do we need an entirely new programming language to overcome the issues in nodejs ? Are the problems so big that they cannot be fixed ? Well no. Many people don’t consider there to be even a problem. But there is one aspect which makes us understand Deno choices, i.e. – Node deviates significantly from the browser’s way of doing things.

For example, take the permissions for when a website wants to record audio; the browser will ask the user to give consent. These kinds of permissions were absent from Node, but Deno brings them back.

The browser does not understand – node_modules/package.json/requiring with extensions /private modules. But Deno makes some of these implementation choices by default, keeps things simple and just as the way a browser would have done. Deno tries to be as close to the browser as possible so that there is minimal friction while porting libraries from front-end to back-end or vice-versa. This can be better in the long term. Afterall, Nodejs allows server-side scripts to run outside of a browser.