Deno is a JavaScript and TypeScript runtime from Ryan Dahl, the creator of Node.js. It addresses some design decisions in Node that Dahl later regretted. Deno runs TypeScript natively, has built-in tools, and defaults to a secure execution model.
What Deno provides
| Feature | Description |
|---|---|
| Native TypeScript | No build step needed for TS |
| Built-in tooling | Formatter, linter, test runner, bundler |
| Secure by default | No file/network access without permission |
| URL imports | Import from URLs, no node_modules by default |
| npm compatibility | Run npm packages with npm: specifier |
| Web standard APIs | Fetch, Web Crypto, streams work natively |
Installation
# macOS/Linux
curl -fsSL https://deno.land/install.sh | sh
# Windows (PowerShell)
irm https://deno.land/install.ps1 | iex
# Or via package managers
brew install deno
Verify installation:
deno --version
Running TypeScript
No configuration needed:
// hello.ts
const message: string = "Hello from Deno!";
console.log(message);
deno run hello.ts
TypeScript just works. No tsconfig, no build step for simple scripts.
Permissions
Deno requires explicit permissions:
# No permissions (fails if code tries to access network)
deno run app.ts
# Allow network access
deno run --allow-net app.ts
# Allow specific hosts
deno run --allow-net=api.example.com app.ts
# Allow file read
deno run --allow-read app.ts
# Allow specific directory
deno run --allow-read=./data app.ts
# Allow environment variables
deno run --allow-env app.ts
# Allow all (like Node.js)
deno run -A app.ts
| Permission | Flag |
|---|---|
| Network | --allow-net |
| File read | --allow-read |
| File write | --allow-write |
| Environment | --allow-env |
| Run subprocesses | --allow-run |
| FFI | --allow-ffi |
| All | -A or --allow-all |
Imports and dependencies
URL imports
import { serve } from "https://deno.land/std@0.220.0/http/server.ts";
import { z } from "https://deno.land/x/zod@v3.22.0/mod.ts";
npm packages
import express from "npm:express@4";
import { z } from "npm:zod";
Import maps
Create deno.json:
{
"imports": {
"@std/": "https://deno.land/std@0.220.0/",
"zod": "npm:zod@3"
}
}
Then import cleanly:
import { serve } from "@std/http/server.ts";
import { z } from "zod";
Built-in tooling
Formatter
deno fmt # Format all files
deno fmt src/ # Format directory
deno fmt --check # Check without writing
Linter
deno lint # Lint all files
deno lint src/ # Lint directory
Test runner
// math_test.ts
import { assertEquals } from "https://deno.land/std@0.220.0/assert/mod.ts";
Deno.test("addition", () => {
assertEquals(1 + 1, 2);
});
deno test
Task runner
In deno.json:
{
"tasks": {
"dev": "deno run --watch --allow-net main.ts",
"test": "deno test --allow-read",
"lint": "deno lint && deno fmt --check"
}
}
deno task dev
Deno vs Node.js
| Aspect | Deno | Node.js |
|---|---|---|
| TypeScript | Native | Requires build step |
| Tooling | Built-in | Separate packages |
| Security | Permissions required | Full access by default |
| Imports | URLs or npm: | node_modules |
| Ecosystem | Growing + npm compat | Massive |
| Deployment | Deno Deploy, Docker | Everywhere |
When to choose Deno
- New projects wanting minimal setup
- Scripts and CLIs
- Projects prioritizing security
- Teams wanting built-in tooling
When to stay with Node.js
- Existing Node.js codebases
- Heavy reliance on Node-specific packages
- Deployment to platforms without Deno support
- Teams experienced with Node ecosystem
Fresh framework
Fresh is Deno's full-stack web framework:
deno run -A -r https://fresh.deno.dev
Features:
- File-based routing
- Islands architecture (partial hydration)
- Server-side rendering
- Zero JavaScript by default
- Deploy to Deno Deploy
// routes/index.tsx
export default function Home() {
return (
<div>
<h1>Welcome to Fresh</h1>
<p>A fresh way to build web apps.</p>
</div>
);
}
HTTP server example
// server.ts
import { serve } from "https://deno.land/std@0.220.0/http/server.ts";
serve((req: Request) => {
const url = new URL(req.url);
if (url.pathname === "/api/hello") {
return Response.json({ message: "Hello from Deno!" });
}
return new Response("Not Found", { status: 404 });
}, { port: 8000 });
console.log("Server running on http://localhost:8000");
deno run --allow-net server.ts
Deployment
Deno Deploy
Deno's edge hosting platform:
# Install deployctl
deno install -A jsr:@deno/deployctl
# Deploy
deployctl deploy --project=my-project main.ts
Docker
FROM denoland/deno:1.40.0
WORKDIR /app
COPY . .
RUN deno cache main.ts
USER deno
EXPOSE 8000
CMD ["run", "--allow-net", "main.ts"]
Summary
Deno offers a modern JavaScript/TypeScript runtime with:
- Native TypeScript without build configuration
- Built-in tools for formatting, linting, testing
- Secure defaults with explicit permissions
- npm compatibility for using existing packages
- Fresh framework for full-stack web development
The Deno documentation and Fresh docs have comprehensive guides for getting started.
