Deno 2.0 — Complete Guide and Features

Sanjeev SharmaSanjeev Sharma
4 min read

Advertisement

Deno is another Node.js alternative, created by the author of Node.js. It fixes Node.js shortcomings with security, permissions, and modern standards.

Why Deno?

  • Security first: Explicit permissions required
  • Modern: Uses ES modules, no package.json
  • TypeScript: Native support
  • Standards: Aligns with browser APIs
  • Tooling: Built-in formatter, linter, testing
# Install Deno
curl -fsSL https://deno.land/x/install/install.sh | sh

# Run TypeScript directly
deno run --allow-read app.ts

# Format code
deno fmt
deno lint

HTTP Server

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

const handler = (req: Request): Response => {
  const url = new URL(req.url);

  if (url.pathname === "/") {
    return new Response("Hello from Deno!");
  }

  if (url.pathname === "/api/users") {
    return Response.json([{ id: 1, name: "Alice" }]);
  }

  return new Response("404 Not Found", { status: 404 });
};

serve(handler, { port: 8000 });
console.log("Server running on http://localhost:8000");

Permissions

Deno requires explicit permissions:

# Allow file system access
deno run --allow-read app.ts
deno run --allow-write app.ts
deno run --allow-net app.ts

# Allow all
deno run --allow-all app.ts

# Specific directory
deno run --allow-read=/path/to/dir app.ts
// Code requires permission to run
const text = await Deno.readTextFile("config.txt");
// Error if --allow-read not provided

const response = await fetch("https://api.example.com");
// Error if --allow-net not provided

File Operations

// Read file
const content = await Deno.readTextFile("file.txt");

// Write file
await Deno.writeTextFile("output.txt", "Hello");

// List directory
for await (const entry of Deno.readDir(".")) {
  console.log(entry.name);
}

// File stats
const stat = await Deno.stat("file.txt");
console.log(`Size: ${stat.size} bytes`);

Standard Library

Deno has a comprehensive standard library:

// HTTP
import { serve } from "https://deno.land/std/http/server.ts";

// Testing
import { assertEquals } from "https://deno.land/std/assert/mod.ts";

// Collections
import { groupBy } from "https://deno.land/std/collections/mod.ts";

// Encoding
import { encodeBase64 } from "https://deno.land/std/encoding/base64.ts";

// UUID
import { v4 } from "https://deno.land/std/uuid/mod.ts";
const id = v4.generate();

Testing

import { assertEquals, assertThrows } from "https://deno.land/std/assert/mod.ts";

Deno.test("addition", () => {
  assertEquals(1 + 1, 2);
});

Deno.test("async operation", async () => {
  const result = await someAsyncFunction();
  assertEquals(result, "expected");
});

Deno.test("should throw", () => {
  assertThrows(() => {
    throw new Error("Oops");
  });
});
deno test
deno test --coverage=./coverage

Using Third-Party Modules

// From deno.land
import { serve } from "https://deno.land/std/http/server.ts";

// From npm via esm.sh
import express from "https://esm.sh/express@4.18.0";

// From npm via jsr (Deno ecosystem)
import { assertEquals } from "jsr:@std/assert";

// Lock file for versions
// deno.lock (auto-generated)

Environment Variables

// Read environment variable
const apiKey = Deno.env.get("API_KEY");
if (!apiKey) {
  throw new Error("API_KEY not set");
}

// Load from .env file
import { load } from "https://deno.land/std/dotenv/mod.ts";
const env = await load();
const databaseUrl = env.DATABASE_URL;
# Set variables
export API_KEY=secret
export DATABASE_URL=postgresql://localhost/db

deno run --allow-env app.ts

Building Applications

CLI Tool

// cli.ts
import { parse } from "https://deno.land/std/flags/mod.ts";

const args = parse(Deno.args, {
  string: ["name"],
  boolean: ["help"],
});

if (args.help) {
  console.log("Usage: deno run cli.ts --name=Alice");
  Deno.exit(0);
}

console.log(`Hello, ${args.name || "World"}!`);
deno run cli.ts --name=Alice
# Hello, Alice!

Web Framework

// oak is a popular Deno web framework
import { Application, Router } from "https://deno.land/x/oak/mod.ts";

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

router.get("/users", (ctx) => {
  ctx.response.body = [{ id: 1, name: "Alice" }];
});

app.use(router.routes());

await app.listen({ port: 8000 });

Comparison: Node vs Deno vs Bun

FeatureNode.jsDenoBun
MaturityStableStableNew
SecurityNoYesNo
TypeScriptVia setupNativeNative
Package managementnpmURL-basedbun pkg
PerformanceGoodGoodExcellent
EcosystemHugeSmallGrowing

FAQ

Q: Should I use Deno instead of Node.js? A: For new projects, Deno is worth considering if you like its philosophy. For existing Node.js teams, the switch cost is high.

Q: Can Deno use npm packages? A: Yes, via esm.sh or jsr. Not all packages work perfectly.

Q: Is Deno production-ready? A: Yes, absolutely. Used by companies in production.


Deno represents the future of JavaScript runtimes — secure by default, modern APIs, and no bloated node_modules. Whether Node.js, Bun, or Deno becomes dominant, all three offer powerful backend development.

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro