Intro to Deno

Intro to Deno

Deno 1.0 officially released on May 13th and I am excited to start using it. Deno has three headline features:

  • Secure Defaults: You need to grand explicit permission for your Deno applications to access disk, network, and runtime environment.
  • Runs TypeScript directly: No tsconfig needed, Deno acts like a native TypeScript runtime (under the covers, it still transpiles and bundles your TypeScript files).
  • Imports ES Modules directly from URLs: No more NPM, dependencies can be imported directly via URL or file path:
import toUpperCase from 'https://flavio-es-modules-example.glitch.me/uppercase.js';

The third feature is generating a lot of debate around package management, especially concerning security. For example, will this prevent another left-pad incident? Regardless of your gut reaction, I highly recommend reading the docs.

Personally, I think the explicitness of import-from-URL will make developers think more carefully about dependency management. However, I suspect many teams will handle this problem similarly to how they handle npm: with lock files, proxies and white-listed internal registries.

Deno also includes less-cited features that I'm excited about:

Enough talk, let's take Deno for a spin by building a simple web app:

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) {
  if (req.url.startsWith("/ping")) {
    req.respond({ status: 200, body: "pong" });
  } else if (req.url.startsWith("/hi")) {
    req.respond({ status: 200, body: "hello there." });
  } else {
    req.respond({ status: 404, body: "Not Found." });
  }
}
Copy these contents and save as demo.ts

This demo uses the HTTP standard library and handles two routes: /ping and /hi. Note the use of for await ... of without an enclosing async IIFE. Install Deno, then run:

# run locally
deno run demo.ts 

# run from remote URL
deno run https://gist.githubusercontent.com/robzhu/ef4e76d27ca50a920a9e5b4aebb40ab9/raw/6bef3fa5eb6bca5f439c3fde75ce2e39cf4cd451/demo.ts

Either way, you should see an error:

error: Uncaught PermissionDenied: network access to "0.0.0.0:8000", run again with the --allow-net flag
    at unwrapResponse ($deno$/ops/dispatch_json.ts:43:11)
    at Object.sendSync ($deno$/ops/dispatch_json.ts:72:10)
    at Object.listen ($deno$/ops/net.ts:51:10)
    at listen ($deno$/net.ts:152:22)
    at serve (https://deno.land/std@0.50.0/http/server.ts:261:20)
    at https://gist.githubusercontent.com/robzhu/ef4e76d27ca50a920a9e5b4aebb40ab9/raw/6bef3fa5eb6bca5f439c3fde75ce2e39cf4cd451/demo.ts:3:11

Since this is an HTTP server, we need to grant explicit permissions for network access.

# run locally
deno run --allow-net demo.ts 

# run from remote URL
deno run --allow-net https://gist.githubusercontent.com/robzhu/ef4e76d27ca50a920a9e5b4aebb40ab9/raw/6bef3fa5eb6bca5f439c3fde75ce2e39cf4cd451/demo.ts

Now you should be able to test your server by navigating to http://localhost:8000/hi. So far so good, but that URL is quite long, is there an easy way to install it as a script?

deno install --allow-net -n denohttp https://gist.githubusercontent.com/robzhu/ef4e76d27ca50a920a9e5b4aebb40ab9/raw/6bef3fa5eb6bca5f439c3fde75ce2e39cf4cd451/demo.ts

# run the script:
denohttp

What are your initial impressions of Deno?