Deno vs Node.js. With code examples and sample app.

Do you see all these posts about Deno and think “So how exactly is Deno different from Node.js?”.

If you are looking for a quick answer, then I’ve prepared a highlight of the differences I noticed yet. Here it is:

Deno supports Typescript out of the box, has a window global object, it doesn’t use a package manager, but caches dependencies on your machine, it has a built-in code formatter and will have linter soon, it can bundle a whole app into a single JS file that can be used in a browser and it has an official style guide.

In this article, I don’t include any benchmark test results, nor highlight the performance advantages of either of the runtimes.

I have no answer in what exact situations Deno is better than Node.js and why you should use it.

This article includes my experience of creating a small, time formatting application using Deno describing things that are different from Node.js way of dealing with things.

The complete code for the time formatting app created using Deno can be found in my Github repository.

Deno has no need for a package manager. So how exactly can I plug third-party libraries to my app?

// main.ts
// No typescript dependecy is needed.
// To run the code in main.ts file just do `deno run ./main.ts`

const main = () => {
  const time = moment() // wait, how can I get the moment?
}

main()

Moment.js is a popular library in the Javascript community that helps you to manage dates. Format dates, parse dates, calculate the time difference between dates, you name it.

So how to import this library to your Deno app? See the code snippet below:

// main.ts

import { moment } from "https://deno.land/x/moment/moment.ts";

const main = () => {
  const time = moment() // nice
}

main()

https://deno.land/x is a public hosting service for ES modules that work with Deno due to the official Deno documentation

So if there is a Javascript library that you might want to use in a Deno app, you should definitely check the list of available options for Deno compatible ES modules.

But what if there is no compatible ES module?

Deno has a collection of standard modules that are claimed to be reviewed by the core Deno team and work perfectly with a particular deno --version

The collection of standard Deno modules can be found here.

If, for example there would not be a moment library available for Deno, I could have checked the native Deno module for working with date/time and see if it can fulfill my needs.

What if there is no standard Deno module that suits my needs?

Then, in my opinion, you have at least two options.

  • Contribute to creating the port of the library you need for Deno and include it to https://deno.land/x
  • Create your own module that would deal with the functionality you are looking for. (I don’t recommend reinventing the wheel so if other options worked for your then you should stick to them)

With that said I’ve chosen a completely different and not recommended approach to use in your apps.

Still, I find it pretty useful for learning purposes so I decided to describe it in detail. Let’s take a look.

To create the date formatting app, I needed to use the fr locale file for moment. It is distributed with the moment library, but it seems that Deno compatible ES module for moment doesn’t include it.

What I’ve tried to do is to visit the moment Github repository and import the locale in my Deno app directly from Github! Amazing isn’t it?

// main.ts

import { moment } from "https://deno.land/x/moment/moment.ts";
import "https://raw.githubusercontent.com/moment/moment/develop/locale/fr.js"

const main = () => {
  const time = moment() // nice
}

main()

It worked perfectly, but this error occurred:

It makes total sense after you take a look to implementation of the https://raw.githubusercontent.com/moment/moment/develop/locale/fr.js

On line 10, you see this used to get the global object:

}(this, (function (moment) { 'use strict';
;(function (global, factory) {
   // some of the logic before
   factory(global.moment)
}(this, (function (moment) { 'use strict';

From what I know, in Deno you can reference a global object by a window or a self link, but not by this referenced outside any function, object, or module like in Node.js or in browsers.

So what I did is I downloaded a fr locale file to my project folder and changed this to self in the local fr.js file.

// }(this, (function (moment) { 'use strict';
}(self, (function (moment) { 'use strict';
// main.ts

import { moment } from "https://deno.land/x/moment/moment.ts";
import "./locale/fr.js"

const main = () => {
  const time = moment() // nice
}

main()

This worked properly, but I don’t recommend using this approach in your applications since if any changes are added to the file by core moment team you would need to sync your local file with the one in moment Github repository.

This approach is absolutely not maintainable so stick to alternative options if possible.

How do you manage your dependencies in Deno comparing to Node.js?

  • deno cache --lock=lock.json --lock-write ./main.ts
  • deno cache -r --lock=lock.json ./main.ts
  • deno info ./main.ts

Let’s try to understand what exactly each command does and when you might need to use it.

main.ts is an entry file to your application

Create a lock file

deno cache --lock=lock.json --lock-write ./main.ts creates a lock.json file that lists the exact dependency versions you used when developed your application.

It has the same purpose as package.lock.json in Node.js.

When someone installs dependencies on their machine, Deno and Node.js (npm) take a lock file as a reference of what dependencies and of what exact versions should be installed.

The lock.json should be committed to your application code.

It should be updated by the same command each time you add or remove any dependency from your app.

How do you install dependencies for your Deno app?

deno cache -r --lock=lock.json ./main.ts unlike Node.js, Deno has no node_modules folder alternative.

When you run the command above all the dependencies are cached on the machine that runs the script.

You can load the app’s dependencies to your machine without a lock file:

deno cache ./main.ts --reload

--reload indicates that cached modules should be upgraded due to what dependencies are required by your application.

More information about --reload you can find in this section in Deno documentation.

You can find out where the cache is located on your machine by running the following command:

deno info

Almost the same command is used to list all the dependencies of your application:

deno info ./main.ts

More in-depth information about managing your dependencies can be found in Deno documentation.

Conclusion

In this article, I’ve highlighted a difference between Deno and Node.js from my perspective of view.

Most of the differences I’ve described are related to dependencies management, but surely it is not the complete list.

Deno has its own code formatting tool, linting tool (an upcoming feature), it has an official style guide, and a few code restrictions that are not present in Node.js, for example, you can’t use a return statement outside of afunction scope.

I haven’t spent enough time using Deno to have a strong opinion about it. I don’t know whether it would replace Node.js or not or why should you choose Deno in a particular situation.

But I know for sure that I had a good time while learning about the possibilities that Deno presents.

I hope you’ve enjoyed the reading and learned a few things with me today! It is always a pleasant feeling to discover something new, isn’t it?

If you are eager to read more, you might want to check my previous article I paired Svelte with Typescript. Here is what I have learned

Contact me at letconstportal@gmail.com and share your feedback about the article, request topics to be highlighted, or just tell me how you are doing.