DEV Community

André Michel Andy
André Michel Andy

Posted on

Let's explore the Deno Lands

On May 13th 2020, a new runtime has been released to the JavaScript ecosystem: Deno. Developed by Ryan Dahl and his team, Deno aims for a better experience in developing Node.js apps. It includes first-class support for TypeScript, a permission scheme that makes our code secure and ESModules as the official way to import packages.
Today is the big day! I am writing this article on the very first day of release, so let’s see what Deno can do and my first impressions.

Installing Deno 🚀

Here are the installation instructions for Deno. I’m using Windows, so this is the command I used in PowerShell:

iwr https://deno.land/x/install/install.ps1 -useb -outf install.ps1; .\install.ps1 v1.0.0

and the result was:

Deno was installed successfully to C:\Users\Andy\.deno\bin\deno.exe
Run 'deno --help' to get started
Enter fullscreen mode Exit fullscreen mode

Well, I'm lying to you a little bit 😅 this was the actual result:

PS C:\Users\Andy> iwr https://deno.land/x/install/install.ps1 -useb -outf install.ps1; .\install.ps1 v1.0.0
File .\install.ps1 : cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at
https:/go.microsoft.com/fwlink/?LinkID=135170.
At line: 1 char: 70
+ ... d/x/install/install.ps1 -useb -outf install.ps1; .\install.ps1 v1.0.0
+                                                      ~~~~~~~~~~~~~
    + CategoryInfo          : SecurityError: (:) [], PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess
Enter fullscreen mode Exit fullscreen mode

But don't worry, just run this command to allow downloaded scripts to be executed:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force
(I am not a PowerShell user, so I will check for a command to revert or change the execution policy to its defaults after the installation. You should do it too)

Let's check if everything is okay with:
deno --version

Ok, everything sees to be fine:

C:\Users\Andy>deno --version
deno 1.0.0
v8 8.4.300
typescript 3.9.2
Enter fullscreen mode Exit fullscreen mode

Running my first "hello world" 🤓

As the tradition says, let's write a hello world in TypeScript

const message: String = "Hello world"; // I used type annotations just to make sure that this TS
console.log(message);
Enter fullscreen mode Exit fullscreen mode

The console says something interesting:

C:\Users\Andy\Desktop\GitHub\DenoExperiments>deno run helloworld.ts
Compile file:///C:/Users/Andy/Desktop/GitHub/DenoExperiments/helloworld.ts
Hello world
Enter fullscreen mode Exit fullscreen mode

But after running it again:

C:\Users\Andy\Desktop\GitHub\DenoExperiments>deno run helloworld.ts
Hello world
Enter fullscreen mode Exit fullscreen mode

Wait, what? Let's make a small change and try again:

C:\Users\Andy\Desktop\GitHub\DenoExperiments>deno run helloworld.ts
Compile file:///C:/Users/Andy/Desktop/GitHub/DenoExperiments/helloworld.ts
Hello world from TS
Enter fullscreen mode Exit fullscreen mode

Ok, now in JS:

C:\Users\Andy\Desktop\GitHub\DenoExperiments>deno run helloworld.js
Hello world from JS
Enter fullscreen mode Exit fullscreen mode

Interesting 🤯 I wasn't expecting that compilation message. Yes, it sounds pretty obvious because TS needs to be compiled before running, but I really thought that no compilation was needed 😅 However, it's great to run TS code without using an external tool.

Time to see the REPL in action:

C:\Users\Andy\Desktop\GitHub\DenoExperiments>deno repl
Deno 1.0.0
exit using ctrl+d or close()
> var hello: String = "hello world"
Uncaught SyntaxError: Unexpected token ':'
    at evaluate ($deno$/repl.ts:45:34)
    at Object.replLoop ($deno$/repl.ts:136:13)
Enter fullscreen mode Exit fullscreen mode

No TS code, only JS. But okay, that idea sounded very unrealistic. If you want to use your own compiler options, just pass them as parameter:

deno run -c tsconfig.json mod.ts

More information at Deno's manual

Integrating with VS Code 💻

At this moment, there are just 5 extensions for Deno in VSCode Marketplace, 2 of them with many reviews:

Deno extensions in VSCode Marketplace

I have installed this, and although it's very limited, it removes TS error messages of URL imports and top-level await (Deno supports it):

Before:
Before the extension

After (it may require a first run):
After the extension

This example is from Deno's website, here's the code

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" });
}
Enter fullscreen mode Exit fullscreen mode

Run it with --allow-net flag or else:
Allow-net flag error

In Deno, we need to grant permissions to some operations like networking, filesystem and running subprocesses.

Exploring third-party packages 📦

Deno has no official package manager (No NPM). You can just import packages just from URLs, so there is no central repository for packages. However, there are some packages listed in Deno's website.

So, what we can do? There's already a web server inspired by Koa, Oak. Also, a ejs template engine.

So, with both packages, we can create an extremely simple CRUD:

// Dependencies
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
import { renderFile } from "https://deno.land/x/dejs/mod.ts";
const { copy, Buffer } = Deno;

const app = new Application();
const router = new Router();

// A CRUD of Dua Lipa's songs
const duaLipaSongs = [{
  name: "Don't start now",
  yearOfRelease: 2019,
}, {
  name: "One kiss",
  yearOfRelease: 2017,
}];

router.get("/index", async (context: any) => {
  // We can use the template engine as always
  const output = await renderFile(`${Deno.cwd()}/template.ejs`, {
    songsList: duaLipaSongs,
  });

  // The file needs to be copied to a buffer
  const buf = new Buffer();
  await copy(output, buf);

  // It can be sent via context.response.body
  context.response.body = new TextDecoder().decode(buf.bytes());
});

router.post("/song", async (context: any) => {
  // Currently, only JSON-encoded body can be read
  const body = await context.request.body();
  duaLipaSongs.push(body.value);

  // There isn't method to redirect a client yet
  context.response.body = "/index";
});

app.use(router.routes());

const PORT = 8080;
// And no way to add an event listener, so maybe this log is not 100% accurate
console.log(`Listening on ${PORT}`);
await app.listen({ port: PORT });

Enter fullscreen mode Exit fullscreen mode

But, what we can do if a script has so many dependencies? We can use named exports from a file named deps.ts

// deps.ts
// Dependencies
export * as Oak from "https://deno.land/x/oak/mod.ts";
export * as Dejs from "https://deno.land/x/dejs/mod.ts";
Enter fullscreen mode Exit fullscreen mode

And now the dependencies are:

// app.ts
// Dependencies
import { Oak, Dejs } from "./deps.ts";
const { Application, Router } = Oak;
const { renderFile } = Dejs;
Enter fullscreen mode Exit fullscreen mode

You can check and download all of the code from here.

Conclusions ✍

Deno comes with a new proposal for developing JavaScript apps. Now, it looks very limited and even slower than Node.js, but everything will improve over time. Today, Deno is NOT a replacement of Node.js, only time will tell what will happen with Deno and Node.js.

If you like this article, please share with your friends or coworkers. Follow me here on DEV, Twitter and GitHub, only if you want. Did I make a mistake? Drop a comment and I will correct it as soon as posible.

Thank you for reading!

Oldest comments (0)