May 16, 2020

Deno and the future of Node.js

Three days ago, the first major version of Deno was released with an accompanying blog post that quickly took the front pages of HackerNews, Twitter, and other communities we tend to spend too much time on. Needless to say, during the past 72 hours, a lot of opinions have been shared on the topic, and I couldn't stop myself from making a few guesses and sharing my own view of the story. With that said, the following is purely my opinion and some points will probably end up developing differently than I anticipated, which is fine.

⏱ How did Deno come to be?

To tell the story of Deno, we should first start more than a decade ago, in times where ES5 was about to be the newest iteration of JavaScript, in a world where jQuery was still around an Ajax was the hot technology everyone wanted to incorporate into their client applications.

In 2009, Ryan Dahl, whose name you might recognize, started working on a project to enable writing server-side applications in JavaScript, based on Google's V8 engine, an event loop, and lots of asynchronous I/O (through libuv). A year later, a package manager and registry, called npm, was published to the public.

More than a decade later, Node.js, as the project was named, is widespread throughout the web development community. Almost all tools based around JavaScript application development depend on it.

Over time, as the adoption started to rise, some fundamental flaws of the architecture became apparent. This shouldn't be seen as bashing Node.js, in fact, I've used it for years now and couldn't imagine and world without it. But due to the constraints of a mostly single-threaded programming model around non-blocking I/O, some applications became harder to scale than people hoped for.

A lot of solutions and workarounds were created to decrease the impact, but even Node.js' creator voiced some regrets connected early decisions that would shape the way users around the globe develop applications (including the use of the notoriously large node_modules directory convention). However, it's also worth mentioning that with billions of people interacting with the technology at one point, this should be expected.

What's rather impressive, over the years, Node.js developed to a platform where developing various types of applications on, supplied with vast learning resources and documentation available, is easier than ever. Only a few communities will compare to the size of the JavaScript ecosystem, which in part is built on the success of Node.js.

Out of the experiences gained from observing how Node.js was used and what the primary pain points were, a group of people including Ryan Dahl formed around a new project, Deno.

🤔 What's Deno anyway?

Advertised as "a secure runtime for JavaScript and TypeScript", Deno is a foundation for building JavaScript apps running outside of the browser.

In contrast to Node.js, Deno attempts to offer a standard library built on web technology primitives already used in real browsers, for example, the fetch API (a long-requested feature in Node.js), or the decision to build asynchronous functionality on top of Promises, instead of the callback hell that was introduced in Node.

Performing network or I/O tasks requires the runtime to have been granted access, which can be done by supplying command-line arguments to enable said features. In its default state, Deno tries to be a sandbox, similar to the isolation levels browsers seek to offer.

Having first-class TypeScript support also offers a level of safety for building applications that wasn't considered necessary a few years ago, but has become the new standard.

Another core feature of Deno is the way dependencies are handled: Including external code like libraries is now done by supplying the URL where the file lives. If you wanted to build a web application using the built-in HTTP API, which you'll import from https://deno.land/std/http/server.ts.

Looking at an example server snippet located on the Deno landing page, some of the core design decisions become apparent:

import { serve } from 'https://deno.land/std@0.50.0/http/server.ts';

const s = serve({ port: 8000 });

console.log('http://localhost:8000/');

for await (const req of s) {
  req.respond({ body: 'Hello World\n' });
}

Gone are the days of EventEmitters, callbacks, CommonJS imports. Instead of all this legacy technology, we're greeted by top-level awaits, a fully-typed standard library, async iterators for handling requests, and much more.

Building applications in this fashion feels like the future, much of which can be credited to the radical process of building the runtime completely from scratch, using all the experience and feedback gained over the years to build it the right way, from day one.

There's more to Deno still, for example, the heavy use of Rust throughout core components, such as custom bindings for V8, which is still used under the hood. The launch post includes a full overview of the basic concepts, so I'd recommend reading it!

🧭 This will be big, soon

It didn't take long for people to jump on the Deno train, announcing the death of Node.js, with Deno emerging as the clearly superior technology.

Focusing merely on the technical aspects does leave little to criticize regarding the direction that Deno is taking, although completely parting from the dependency ecosystem is a radical change. There are, however, vendors that already pursue the vision of making important packages compatible with Deno.

And still, I believe that Deno will need more time to grow to a point where teams adopt it without second thoughts or even get the buy-in from higher-ups. Sure, the security benefits are great and all, but there's still a lot left to be built before entire organizations can adopt Deno. It's also not the way technology adoption works.

In the next weeks, we'll see some adventurous companies announce first plans to investigate what this new technology is about, in the meantime a lot of new libraries, projects, and other open-source work will be kicked off by a growing community.

In a few months, if growth continues to impress, we'll likely see vendors like Vercel (formerly ZEIT) announcing runtime support, followed by other cloud vendors that catch on to the trend.

Once we're at a point where Deno support starts to become as widespread as Node.js is today, with all tools ready for people to build production-grade services, Node.js might start to vanish, which I still doubt. It's not that Deno isn't impressive or that it'll become the go-to choice for backend JavaScript development, it's that so many different parties use Node.js for the most extreme use cases, that switching to a different runtime with radically different core concepts, will take longer than most would expect.

Whatever the actual timeline turns out to be, I'm thrilled to see what's to come out of Deno. I've already started playing around with some thoughts, I'll probably attempt to get some tools running on Deno, but I think only time can tell the real trajectory we're about to experience.


Thank you for reading this post about my opinion on the recent launch of Deno v1! If you've got any feedback, or think different, don't hesitate to reach out on Twitter or by mail.