DEV Community

Alex Spinov
Alex Spinov

Posted on

Deno 2 Has a Free API That Makes It a Drop-In Replacement for Node.js

Deno 2 is the Node.js-compatible runtime with built-in TypeScript, testing, linting, and package management. It runs npm packages natively.

npm Compatibility: Just Works

// Import npm packages directly
import express from "npm:express";
import { PrismaClient } from "npm:@prisma/client";
import chalk from "npm:chalk";

const app = express();
app.get("/", (req, res) => res.json({ hello: "world" }));
app.listen(3000);
Enter fullscreen mode Exit fullscreen mode

No node_modules by default. Deno downloads and caches packages automatically.

Built-In Tools

# TypeScript — no tsconfig needed
deno run server.ts

# Testing
deno test

# Linting
deno lint

# Formatting
deno fmt

# Type checking
deno check server.ts

# Benchmarking
deno bench

# Task runner (like npm scripts)
deno task build
Enter fullscreen mode Exit fullscreen mode

Deno.serve: Zero-Dependency Server

Deno.serve({ port: 3000 }, async (req) => {
  const url = new URL(req.url);

  if (url.pathname === "/api/products" && req.method === "GET") {
    const data = await getProducts();
    return Response.json(data);
  }

  if (url.pathname === "/api/scrape" && req.method === "POST") {
    const { url: targetUrl } = await req.json();
    const html = await fetch(targetUrl).then(r => r.text());
    return Response.json({ html: html.slice(0, 1000) });
  }

  return new Response("Not Found", { status: 404 });
});
Enter fullscreen mode Exit fullscreen mode

Deno KV: Built-In Database

const kv = await Deno.openKv();

// Set values
await kv.set(["products", "123"], { title: "Widget", price: 29.99 });

// Get values
const result = await kv.get(["products", "123"]);
console.log(result.value); // { title: "Widget", price: 29.99 }

// List by prefix
const entries = kv.list({ prefix: ["products"] });
for await (const entry of entries) {
  console.log(entry.key, entry.value);
}

// Atomic operations
await kv.atomic()
  .check({ key: ["products", "123"], versionstamp: result.versionstamp })
  .set(["products", "123"], { ...result.value, price: 24.99 })
  .commit();

// Enqueue background jobs
await kv.enqueue({ type: "scrape", url: "https://example.com" });
kv.listenQueue(async (msg) => {
  if (msg.type === "scrape") await scrapeUrl(msg.url);
});
Enter fullscreen mode Exit fullscreen mode

Deno.cron: Scheduled Tasks

Deno.cron("scrape prices", "0 * * * *", async () => {
  const products = await scrapeProducts();
  for (const p of products) {
    await kv.set(["products", p.id], p);
  }
});

Deno.cron("cleanup old data", "0 0 * * *", async () => {
  const entries = kv.list({ prefix: ["products"] });
  for await (const { key, value } of entries) {
    if (Date.now() - value.scrapedAt > 30 * 24 * 60 * 60 * 1000) {
      await kv.delete(key);
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

Permissions: Security by Default

# Granular permissions
deno run --allow-net=api.example.com --allow-read=./data --allow-env=API_KEY server.ts

# Or allow all (development)
deno run -A server.ts
Enter fullscreen mode Exit fullscreen mode

Build scraping tools with Deno? My Apify tools are runtime-agnostic.

Custom Deno solution? Email spinov001@gmail.com

Top comments (0)