blog.dopana

Back

Deno là runtime cho JavaScript và TypeScript — tạo bởi chính Ryan Dahl (tác giả Node.js). Học từ sai lầm của Node.

Node.js (2009):  npm, node_modules, CommonJS, callback
Deno (2020):     URL import, không node_modules, ESM, async/await, TypeScript
plaintext

Tại Sao Deno?#

Vấn đề với Node.js#

Ryan Dahl liệt kê 10 điều hối tiếc về Node trong bài talk “10 Things I Regret About Node.js”:

  • Promise thay vì callback (đã fix)
  • Security (không sandbox)
  • Module system (CommonJS vs ESM mess)
  • node_modules nặng
  • package.json phình to
  • TypeScript không native

Deno giải quyết tất cả.

So Sánh#

Node.jsDeno
TypeScriptCần tsconfig + ts-nodeNative
Modulenpm + node_modulesURL import + npm (JSR)
SecurityFull accessPermissions opt-in
Package managernpm/yarn/pnpmKhông cần
Configpackage.json, tsconfig,…deno.json (tuỳ chọn)
Standard librarynpm packagesstd (deno.land/std)
Web APIfetch, AbortController…✅ All Web API
Binary1 file?1 file (~30MB)

Cài Đặt#

# macOS / Linux
curl -fsSL https://deno.land/install.sh | sh

# macOS (Homebrew)
brew install deno

# Windows
winget install DenoLand.Deno

# Verify
deno --version
deno --help
bash

Hello World#

// hello.ts
console.log('Hello Deno!')

// Chạy — không cần config, không cần package.json
deno run hello.ts
typescript
# Cấp quyền network
deno run --allow-net server.ts

# Cấp quyền đọc file
deno run --allow-read file.ts

# Cấp tất cả (không khuyến khích)
deno run -A script.ts
bash

Permissions#

Deno an toàn mặc định — script không có quyền gì:

// Không chạy được — cần --allow-net
const res = await fetch('https://api.example.com')

// Không chạy được — cần --allow-read
const text = await Deno.readTextFile('/etc/hosts')

// Không chạy được — cần --allow-env
console.log(Deno.env.get('HOME'))
typescript
# Grant từng quyền
deno run --allow-net=api.example.com --allow-read=/tmp script.ts

# Prompt quyền khi cần (interactive)
deno run --allow-prompt script.ts
bash

Permissions: --allow-read, --allow-write, --allow-net, --allow-env, --allow-run, --allow-ffi, --allow-sys, --allow-hrtime.

TypeScript Native#

// deno.json — optional config (thay thế package.json + tsconfig)
{
  "tasks": {
    "dev": "deno run --watch --allow-net src/main.ts",
    "start": "deno run --allow-net --allow-read src/main.ts",
    "test": "deno test"
  },
  "imports": {
    "express": "npm:express@5",
    "std/": "https://deno.land/std@0.224.0/"
  }
}
json

Module: URL Import#

Không npm install, không node_modules:

// Import từ URL — Deno cache tự động
import { serve } from 'https://deno.land/std@0.224.0/http/server.ts'
import { Hono } from 'https://deno.land/x/hono/mod.ts'

// Import từ npm (Deno 2+)
import express from 'npm:express@5'

// Import từ JSR (Deno registry mới)
import { z } from 'jsr:@std/zod'
typescript
Cache ở:
~/.cache/deno/  (macOS/Linux)
%LOCALAPPDATA%/deno/ (Windows)
plaintext

Không npm install, không node_modules, không package-lock.json cho URL imports.

HTTP Server#

deno run --allow-net server.ts
bash

File System#

// Deno API — promise-based
const content = await Deno.readTextFile('./data.json')
const data = JSON.parse(content)

await Deno.writeTextFile('./output.txt', 'Hello Deno!')

// Web API
const json = await Deno.readTextFile('./config.json')
const config = JSON.parse(json)

// Streaming
const file = await Deno.open('./large-file.txt')
for await (const chunk of file.readable) {
  // process chunk
}
typescript

Standard Library#

Deno có std library chính thức — không cần npm packages cho common tasks:

Testing#

Testing built-in — không cần Jest/Vitest:

// math_test.ts
import { assertEquals } from 'https://deno.land/std@0.224.0/assert/mod.ts'

Deno.test('add two numbers', () => {
  const result = 1 + 2
  assertEquals(result, 3)
})

Deno.test('async test', async () => {
  const res = await fetch('https://api.example.com')
  assertEquals(res.status, 200)
})
typescript
# Chạy test
deno test
deno test --allow-net # Nếu test cần network
deno test --watch # Watch mode
deno test --coverage # Coverage
bash

Deno 2.x Features#

Deno 2 (2024+) thêm tương thích ngược với Node.js/npm:

{
  "imports": {
    "express": "npm:express@5",
    "react": "npm:react@19",
    "lodash": "npm:lodash@4"
  }
}
json
// Chạy package.json project với Deno
deno run npm:next start

// Dùng npm packages
import express from 'npm:express@5'
const app = express()
app.get('/', (req, res) => res.send('Hello from Deno!'))
app.listen(3000)
typescript

Deno 2 có thể chạy hầu hết Node.js projects — chỉ cần deno run thay node.

So Sánh: Node vs Deno#

// Node.js
const http = require('http')
http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' })
  res.end('Hello Node\n')
}).listen(3000)

// Deno
Deno.serve({ port: 3000 }, (req) => {
  return new Response('Hello Deno')
})

// Deno dùng Web API — giống browser
typescript
TaskNodeDeno
HTTP serverhttp.createServerDeno.serve (Web API)
File readfs.readFileSyncDeno.readTextFile
Environmentprocess.envDeno.env.get
TypeScriptts-node, tsconfigNative
TestJest, VitestDeno.test
FormatPrettierdeno fmt
LintESLintdeno lint
Compilepkg, nexedeno compile

Toolchain#

Deno là runtime + toolchain trong một binary:

deno run # Run script
deno test # Test runner
deno fmt # Formatter (Prettier alternative)
deno lint # Linter (ESLint alternative)
deno doc # Documentation generator
deno compile # Compile to single binary
deno bench # Benchmark runner
deno task # Run tasks (package.json scripts)
deno check # Type-check
deno init # Init project
bash
# Format code
deno fmt

# Lint
deno lint

# Compile thành binary standalone
deno compile --allow-net --output my-app src/main.ts
# → my-app (single binary, ~30MB, chạy không cần Deno)
bash

Khi Nào Dùng Deno?#

✅ Nên dùng#

  • CLI tool / script — TypeScript native, không config
  • HTTP API nhỏ-gọn — Deno.serve + std library đủ
  • Security-sensitive app — permissions model
  • New project — không muốn npm baggage
  • Single binary distribution — deno compile

❌ Không nên#

  • Large Node.js project — migration không đáng
  • Cần nhiều npm packages — Node ecosystem vẫn lớn hơn
  • Team quen Node — không cần đổi nếu đang ổn
  • Serverless (Lambda) — Deno hỗ trợ nhưng Node nhiều hơn

Tổng Kết#

Deno sửa những gì Node làm sai — security, modules, TypeScript, toolchain.

# Deno: một binary cho mọi thứ
deno run --allow-net server.ts # Run server
deno test # Test
deno fmt # Format
deno lint # Lint
deno compile # Build binary
deno doc # Docs

# Không npm install, không node_modules, không tsconfig
# Chỉ import từ URL, chạy luôn
bash
Node.jsDeno
Security❌ Full access✅ Permissions
TypeScript❌ tsconfig + ts-node✅ Native
Module❌ npm + node_modules✅ URL import + npm
Toolchain❌ Rời rạc (ESLint, Prettier, Jest)✅ Một binary
Web API⚠️ Một phần✅ Đầy đủ
Standard lib✅ Qua npm✅ std + JSR

Deno không “thay thế Node” — nó là alternative cho những ai muốn runtime an toàn hơn, TypeScript native, ít toolchain hơn.

Tài liệu tham khảo#