Deno 2 — JavaScript Runtime Thế Hệ Mới: Bảo Mật, TypeScript Native và Tương Thích NPM
Posted on: 4/26/2026 1:13:51 AM
Table of contents
- 1. Tại sao cần Deno khi đã có Node.js?
- 2. Kiến trúc Deno Runtime
- 3. Hệ thống Permission — Bảo mật mặc định
- 4. TypeScript Native — Không cần cấu hình
- 5. Hệ thống Module — URL Import + NPM Compatibility
- 6. Công cụ tích hợp — All-in-One Toolchain
- 7. dx — npx cho Deno
- 8. Deno Deploy — Serverless Runtime trên Edge
- 9. So sánh Deno 2.6 vs Node.js 22 vs Bun 1.2
- 10. Deno với Hono — Xây API Production
- 11. WebAssembly Source Phase Imports
- 12. Migration từ Node.js sang Deno
- 13. Khi nào KHÔNG nên dùng Deno?
- 14. Tổng kết
Trong thế giới JavaScript runtime, Node.js đã thống trị hơn 15 năm. Nhưng từ khi Deno 2.0 ra mắt cuối 2024 và liên tục cải tiến đến phiên bản 2.6 hiện tại, cuộc chơi đã thay đổi hoàn toàn. Deno không chỉ là "Node.js viết lại" — đây là runtime được thiết kế lại từ đầu bởi chính Ryan Dahl (cha đẻ Node.js), sửa triệt để những sai lầm thiết kế mà ông thừa nhận sau hơn một thập kỷ.
1. Tại sao cần Deno khi đã có Node.js?
Ryan Dahl trình bày "10 Things I Regret About Node.js" tại JSConf EU 2018, liệt kê các quyết định thiết kế sai lầm: không có security , hệ thống module dựa trên node_modules cồng kềnh, thiếu TypeScript native, và API không theo Web Standards. Deno ra đời để giải quyết tất cả những vấn đề này.
Triết lý thiết kế Deno
Secure by default — không có quyền truy cập file, network, hay environment variables cho đến khi developer cho phép rõ ràng. Đây là đảo ngược hoàn toàn so với Node.js, nơi mọi script đều có toàn quyền hệ thống.
2. Kiến trúc Deno Runtime
graph TB
A[Deno CLI] --> B[V8 Engine]
A --> C[Rust Core - Tokio]
A --> D[TypeScript Compiler - swc]
B --> E[JavaScript Execution]
C --> F[Async I/O Runtime]
D --> G[Type Checking + Transpilation]
F --> H[File System]
F --> I[Network]
F --> J[Subprocess]
K[Permission System] --> H
K --> I
K --> J
L[Web Standard APIs] --> M[fetch, Request, Response]
L --> N[WebSocket, Streams]
L --> O[URL, TextEncoder/Decoder]
style A fill:#e94560,stroke:#fff,color:#fff
style K fill:#4CAF50,stroke:#fff,color:#fff
style L fill:#2c3e50,stroke:#fff,color:#fff
style B fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style C fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style D fill:#f8f9fa,stroke:#e94560,color:#2c3e50
Kiến trúc tổng quan Deno Runtime — V8 + Rust + Permission System
Deno được xây dựng bằng Rust thay vì C++ (như Node.js), sử dụng Tokio làm async runtime. Điều này mang lại memory safety và hiệu năng vượt trội. TypeScript được transpile bằng swc (viết bằng Rust), nhanh hơn 20-70x so với trình biên dịch TypeScript chính thức.
3. Hệ thống Permission — Bảo mật mặc định
Đây là điểm khác biệt lớn nhất của Deno. Mỗi chương trình chạy trong mà không có quyền gì cả:
# Không cho phép bất kỳ quyền nào — script chỉ tính toán thuần
deno run compute.ts
# Cho phép đọc file trong thư mục data/ và truy cập network đến api.example.com
deno run --allow-read=./data --allow-net=api.example.com app.ts
# Cho phép tất cả (không khuyến khích trong production)
deno run -A app.ts
| Permission Flag | Mô tả | Ví dụ |
|---|---|---|
--allow-read | Đọc file system | --allow-read=./config,./data |
--allow-write | Ghi file system | --allow-write=./output |
--allow-net | Truy cập mạng | --allow-net=api.github.com |
--allow-env | Biến môi trường | --allow-env=API_KEY,NODE_ENV |
--allow-run | Chạy subprocess | --allow-run=git,npm |
--allow-ffi | Foreign Function Interface | --allow-ffi=./libcrypto.so |
--allow-sys | Thông tin hệ thống | --allow-sys=hostname,osRelease |
Permission Sets trong Deno 2.5+
Từ Deno 2.5, bạn có thể định nghĩa Permission Sets trong deno.json — nhóm các permission lại thành profile có tên, tái sử dụng cho nhiều script. Tương tự khái niệm Security Policy trong .NET.
4. TypeScript Native — Không cần cấu hình
Deno hiểu TypeScript trực tiếp, không cần tsconfig.json, không cần ts-node, không cần build step:
// server.ts — chạy trực tiếp: deno run --allow-net server.ts
const handler = (request: Request): Response => {
const url = new URL(request.url);
if (url.pathname === "/api/health") {
return Response.json({
status: "ok",
runtime: "deno",
version: Deno.version.deno
});
}
if (url.pathname === "/api/users" && request.method === "GET") {
const users: Array<{ id: number; name: string }> = [
{ id: 1, name: "Anh Tú" },
{ id: 2, name: "Minh Khoa" },
];
return Response.json(users);
}
return new Response("Not Found", { status: 404 });
};
Deno.serve({ port: 8000 }, handler);
console.log("Server running on http://localhost:8000");
Chú ý: API Deno.serve() sử dụng Web Standard Request/Response — giống hệt API của Cloudflare Workers, Bun, và các edge runtime khác. Code viết cho Deno có thể chạy trên các platform này với rất ít thay đổi.
4.1 Type Checker tsgo — Tốc độ kiểm tra kiểu cải thiện hàng chục lần
Deno 2.6 tích hợp tsgo — type checker thử nghiệm viết bằng Go, nhanh hơn đáng kể so với trình kiểm tra TypeScript chuẩn. Điều này đặc biệt hữu ích cho các dự án lớn nơi type checking mất hàng phút:
# Dùng tsgo cho type checking nhanh hơn
deno check --unstable-tsgo main.ts
# So sánh tốc độ
time deno check main.ts # ~8.2s (TypeScript chuẩn)
time deno check --unstable-tsgo main.ts # ~0.9s (tsgo)
5. Hệ thống Module — URL Import + NPM Compatibility
Deno hỗ trợ 3 cách import module:
// 1. Import từ URL (Deno-native, dùng JSR registry)
import { Application } from "jsr:@oak/oak@17";
// 2. Import từ NPM (tương thích hoàn toàn từ Deno 2.0)
import express from "npm:express@5";
import { PrismaClient } from "npm:@prisma/client";
// 3. Import từ node: protocol (Node.js built-in modules)
import { readFile } from "node:fs/promises";
import { createServer } from "node:http";
graph LR
A[Source Code] --> B{Import Type?}
B -->|jsr:| C[JSR Registry]
B -->|npm:| D[NPM Registry]
B -->|node:| E[Node.js Compat Layer]
B -->|https://| F[URL Import]
C --> G[Deno Cache
~/.cache/deno]
D --> G
E --> H[Built-in Polyfills]
F --> G
G --> I[V8 Execution]
H --> I
style A fill:#e94560,stroke:#fff,color:#fff
style G fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style I fill:#2c3e50,stroke:#fff,color:#fff
Luồng resolve module trong Deno — hỗ trợ JSR, NPM, Node.js built-in và URL
Không còn node_modules
Deno cache module vào một thư mục global (~/.cache/deno), không tạo node_modules trong project. Điều này tiết kiệm disk space đáng kể — một dự án trung bình giảm từ 200-500MB xuống gần 0MB trong thư mục project. Tuy nhiên, bạn vẫn có thể bật "nodeModulesDir": "auto" trong deno.json nếu cần tương thích với tooling cũ.
5.1 JSR — JavaScript Registry thế hệ mới
JSR (jsr.io) là registry mới do team Deno xây dựng, thiết kế cho TypeScript-first. Khác với NPM, JSR yêu cầu package publish source TypeScript gốc và tự động tạo type declarations, documentation, và compatibility layers:
// deno.json — cấu hình đơn giản, không cần package.json
{
"tasks": {
"dev": "deno run --watch --allow-net --allow-read server.ts",
"test": "deno test --allow-read",
"lint": "deno lint",
"fmt": "deno fmt"
},
"imports": {
"@std/http": "jsr:@std/http@1",
"@std/assert": "jsr:@std/assert@1",
"hono": "jsr:@hono/hono@4"
}
}
6. Công cụ tích hợp — All-in-One Toolchain
Deno đi kèm mọi công cụ phát triển cần thiết, không cần cài thêm bất kỳ package nào:
| Công cụ | Lệnh Deno | Tương đương Node.js |
|---|---|---|
| Test runner | deno test | Jest / Vitest / Mocha |
| Formatter | deno fmt | Prettier |
| Linter | deno lint | ESLint |
| Type checker | deno check | tsc |
| Bundler | deno compile | esbuild / webpack |
| Task runner | deno task | npm scripts |
| Package runner | dx | npx |
| Security audit | deno audit | npm audit |
| Documentation | deno doc | TypeDoc |
| Benchmarking | deno bench | benchmarkjs |
| REPL | deno repl | node (REPL) |
// user_service_test.ts — Deno test với BDD style
import { assertEquals, assertRejects } from "jsr:@std/assert";
interface User {
id: number;
name: string;
email: string;
}
function validateEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
Deno.test("validateEmail - email hợp lệ", () => {
assertEquals(validateEmail("tu@anhtu.dev"), true);
assertEquals(validateEmail("admin@example.com"), true);
});
Deno.test("validateEmail - email không hợp lệ", () => {
assertEquals(validateEmail("invalid"), false);
assertEquals(validateEmail("@example.com"), false);
assertEquals(validateEmail("user@"), false);
});
Deno.test({
name: "fetch API - trả về dữ liệu đúng format",
permissions: { net: ["jsonplaceholder.typicode.com"] },
async fn() {
const res = await fetch("https://jsonplaceholder.typicode.com/users/1");
const user: User = await res.json();
assertEquals(typeof user.id, "number");
assertEquals(typeof user.name, "string");
},
});
7. dx — npx cho Deno
Deno 2.6 giới thiệu dx — công cụ chạy binary từ NPM và JSR packages mà không cần cài đặt global:
# Chạy Vite trực tiếp
dx vite create my-vue-app
# Chạy package từ JSR
dx jsr:@anthropic/claude-code
# Chạy Prisma CLI
dx prisma migrate dev
# Tạo project Hono
dx create-hono my-api
8. Deno Deploy — Serverless Runtime trên Edge
Deno không chỉ là runtime local — Deno Deploy là nền tảng serverless chạy code trên 35+ edge locations toàn cầu, với cold start dưới 10ms:
graph TB
A[Developer] -->|git push| B[GitHub Repository]
B -->|Auto Deploy| C[Deno Deploy Platform]
C --> D[Edge Location
Singapore]
C --> E[Edge Location
Tokyo]
C --> F[Edge Location
Frankfurt]
C --> G[Edge Location
US East]
D --> H[Users APAC]
E --> I[Users Japan]
F --> J[Users Europe]
G --> K[Users Americas]
C --> L[Deno KV
Global Database]
C --> M[Deno Cron
Scheduled Tasks]
C --> N[Deno Queues
Message Queue]
style A fill:#e94560,stroke:#fff,color:#fff
style C fill:#2c3e50,stroke:#fff,color:#fff
style L fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style M fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style N fill:#f8f9fa,stroke:#e94560,color:#2c3e50
Deno Deploy — Serverless edge deployment với KV, Cron, và Queues tích hợp
// API đơn giản trên Deno Deploy với KV storage
const kv = await Deno.openKv();
Deno.serve(async (request: Request) => {
const url = new URL(request.url);
if (url.pathname === "/api/visit") {
// Atomic increment view counter
const key = ["visits", new Date().toISOString().slice(0, 10)];
await kv.atomic()
.sum(key, 1n)
.commit();
const result = await kv.get<bigint>(key);
return Response.json({
date: key[1],
visits: Number(result.value ?? 0n)
});
}
if (url.pathname === "/api/cache" && request.method === "POST") {
const { key, value, ttl } = await request.json();
await kv.set(["cache", key], value, {
expireIn: ttl * 1000
});
return Response.json({ cached: true });
}
return new Response("Deno Deploy API", { status: 200 });
});
9. So sánh Deno 2.6 vs Node.js 22 vs Bun 1.2
| Tiêu chí | Deno 2.6 | Node.js 22 | Bun 1.2 |
|---|---|---|---|
| Ngôn ngữ core | Rust + V8 | C++ + V8 | Zig + JavaScriptCore |
| TypeScript | Native, không cần config | Cần ts-node/tsx | Native |
| Security | Sandbox mặc định, granular permissions | Experimental permission model | Không có |
| NPM Support | 97%+ tương thích | 100% (native) | ~95% tương thích |
| Built-in Tools | Test, Lint, Fmt, Bench, Doc, Audit | Test runner (basic) | Test, Bundler |
| HTTP Server | ~120K req/s | ~80K req/s | ~160K req/s |
| Cold Start | ~25ms | ~40ms | ~10ms |
| Web Standards | fetch, Request, Response, Streams, WebSocket native | fetch (từ v18), partial | fetch, partial |
| Package Registry | JSR + NPM | NPM | NPM |
| Edge Deploy | Deno Deploy (tích hợp) | Cần third-party | Không có |
| Single Executable | deno compile | SEA (thử nghiệm) | bun build --compile |
Khi nào nên chọn Deno?
Chọn Deno khi ưu tiên bảo mật (chạy code third-party), cần TypeScript native không config, muốn all-in-one toolchain, hoặc cần deploy lên edge. Chọn Node.js khi cần hệ sinh thái NPM 100% và có nhiều legacy code. Chọn Bun khi ưu tiên tốc độ thuần trên mọi benchmark.
10. Deno với Hono — Xây API Production
Kết hợp Deno với Hono framework tạo nên stack API hiệu năng cao, type-safe, và portable:
import { Hono } from "jsr:@hono/hono@4";
import { cors } from "jsr:@hono/hono@4/cors";
import { logger } from "jsr:@hono/hono@4/logger";
import { validator } from "jsr:@hono/hono@4/validator";
type Bindings = {
DB: Deno.Kv;
};
const app = new Hono<{ Bindings: Bindings }>();
app.use("*", logger());
app.use("/api/*", cors({ origin: "https://anhtu.dev" }));
app.get("/api/posts", async (c) => {
const kv = await Deno.openKv();
const entries = kv.list<{ title: string; slug: string }>({
prefix: ["posts"]
});
const posts = [];
for await (const entry of entries) {
posts.push(entry.value);
}
return c.json({ data: posts, total: posts.length });
});
app.post("/api/posts",
validator("json", (value, c) => {
if (!value.title || typeof value.title !== "string") {
return c.json({ error: "Title is required" }, 400);
}
return value as { title: string; body: string };
}),
async (c) => {
const { title, body } = c.req.valid("json");
const kv = await Deno.openKv();
const id = crypto.randomUUID();
await kv.set(["posts", id], {
id, title, body,
createdAt: new Date().toISOString()
});
return c.json({ id, title }, 201);
}
);
Deno.serve({ port: 3000 }, app.fetch);
11. WebAssembly Source Phase Imports
Deno 2.6 hỗ trợ Source Phase Imports cho WebAssembly — import module Wasm trực tiếp trong code TypeScript mà không cần fetch runtime:
// Import Wasm module dưới dạng source
import source wasmModule from "./optimized_algo.wasm";
// Instantiate với imports
const instance = await WebAssembly.instantiate(wasmModule, {
env: {
log: (ptr: number, len: number) => {
// Xử lý logging từ Wasm
}
}
});
// Gọi exported function
const result = instance.exports.fibonacci(42);
console.log(`Fibonacci(42) = ${result}`);
12. Migration từ Node.js sang Deno
deno.json với "nodeModulesDir": "auto" để Deno tự tạo node_modules cho các NPM package. Đổi scripts sang "tasks".require() bằng ESM import. Deno hỗ trợ CJS qua npm: specifier nhưng khuyến khích ESM. Các built-in Node.js dùng prefix node: (ví dụ import fs from "node:fs").Deno.test() hoặc giữ nguyên nếu dùng Vitest (Deno tương thích). Thêm permission flags cho test cần network/file access.npm ci && npm test bằng deno test --allow-read --allow-net. Deno cài đặt bằng một dòng: curl -fsSL https://deno.land/install.sh | sh.deno compile cho self-hosting.13. Khi nào KHÔNG nên dùng Deno?
Hạn chế cần lưu ý
- Native addons — Các package dùng C++ native addons (node-gyp) có thể không tương thích. Ví dụ: bcrypt (dùng
bcryptjsthay thế), sharp (dùng Wasm build). - Ecosystem maturity — Một số framework lớn (NestJS, AdonisJS) chưa hỗ trợ Deno chính thức, dù có thể chạy qua compatibility layer.
- Enterprise tooling — Nếu team đang dùng nặng npm workspaces, Lerna, hoặc Nx cho monorepo, migration sẽ phức tạp hơn.
- Serverless platforms — AWS Lambda, Azure Functions chưa hỗ trợ Deno runtime native (cần custom runtime hoặc compile thành binary).
14. Tổng kết
Deno 2 không còn là thí nghiệm — đây là runtime production-ready với triết lý thiết kế hiện đại: bảo mật mặc định, TypeScript native, Web Standards first, và all-in-one toolchain. Với khả năng tương thích NPM 97%+, JSR registry mới, và Deno Deploy cho edge deployment, Deno đang trở thành lựa chọn nghiêm túc cho các dự án JavaScript/TypeScript mới.
Nếu bạn đang bắt đầu dự án mới và không bị ràng buộc bởi hệ sinh thái Node.js legacy, Deno xứng đáng là runtime đầu tiên cần cân nhắc — đặc biệt khi bảo mật và developer experience là ưu tiên hàng đầu.
Nguồn tham khảo
Nuxt 4 — Fullstack Vue Framework cho Production 2026
Redis Streams — Event Streaming Nhẹ Nhàng Thay Thế Kafka Cho Microservices
Disclaimer: The opinions expressed in this blog are solely my own and do not reflect the views or opinions of my employer or any affiliated organizations. The content provided is for informational and educational purposes only and should not be taken as professional advice. While I strive to provide accurate and up-to-date information, I make no warranties or guarantees about the completeness, reliability, or accuracy of the content. Readers are encouraged to verify the information and seek independent advice as needed. I disclaim any liability for decisions or actions taken based on the content of this blog.