DevToolBox免费
博客

Deno 完全指南:安全的 JavaScript 运行时

24 min read作者 DevToolBox Team

Deno 是一个现代、安全的 JavaScript 和 TypeScript 运行时,基于 V8 引擎,使用 Rust 编写。由 Ryan Dahl(Node.js 的原始创建者)打造,Deno 通过提供一流的 TypeScript 支持、默认安全的权限系统、内置工具(格式化器、检查器、测试运行器、打包器)、Web 标准 API 和原生 npm 兼容性来解决 Node.js 的设计缺憾。本指南涵盖从 Deno 基础到生产部署的所有内容。

TL;DR

Deno 是使用 Rust 编写的安全 JavaScript/TypeScript 运行时。它原生运行 TypeScript,通过细粒度权限系统实施安全性,包含丰富的标准库,原生支持 npm 包,提供内置工具(deno fmt、deno lint、deno test、deno bench),使用 deno.json 配置项目和任务,提供 Deno.serve() 高性能 HTTP 服务器,并通过 Deno Deploy 部署到边缘。Fresh 框架提供基于岛屿的 SSR。

Key Takeaways
  • Deno 原生运行 TypeScript 和 JSX/TSX,无需任何构建步骤、转译器配置或 tsconfig.json。
  • 权限系统默认安全:脚本无法访问文件系统、网络或环境,除非明确授予权限标志。
  • Deno 标准库(jsr:@std)提供稳定的、经过审查的 HTTP、文件系统、测试、加密和异步工具模块。
  • 通过 npm: 说明符的原生 npm 兼容性意味着绝大多数 npm 生态系统可在 Deno 中无需修改即可工作。
  • 内置工具替代了整个类别的第三方包:deno fmt(Prettier)、deno lint(ESLint)、deno test(Jest)、deno bench。
  • Deno Deploy 提供全球分布式边缘托管,具有亚毫秒级冷启动、自动 HTTPS 和从 GitHub 零配置部署。

Deno 基础:安装和第一步

Deno 作为单个二进制可执行文件分发,没有外部依赖。安装只需几秒钟,即可获得完整的开发环境。

在任何平台上安装 Deno:

# Install Deno (macOS / Linux)
curl -fsSL https://deno.land/install.sh | sh

# Install Deno (Windows PowerShell)
irm https://deno.land/install.ps1 | iex

# Install via Homebrew (macOS)
brew install deno

# Verify installation
deno --version
# deno 2.x.x
# v8 12.x.x
# typescript 5.x.x

# Initialize a new project
deno init my-app
cd my-app
# Creates: main.ts, main_test.ts, deno.json

# Useful commands
deno run main.ts          # Run a script
deno run --watch main.ts  # Run with auto-reload
deno fmt                  # Format code
deno lint                 # Lint code
deno test                 # Run tests
deno bench                # Run benchmarks
deno compile main.ts      # Compile to binary

你的第一个 Deno 脚本直接运行 TypeScript:

// main.ts — runs directly with: deno run main.ts
interface User {
  name: string;
  age: number;
  email: string;
}

function greet(user: User): string {
  return "Hello, " + user.name + "! You are " + user.age + " years old.";
}

const user: User = {
  name: "Alice",
  age: 30,
  email: "alice@example.com",
};

console.log(greet(user));

// Fetch data from a URL (web-standard fetch)
const response = await fetch("https://api.github.com/zen");
const wisdom = await response.text();
console.log("GitHub Zen:", wisdom);

安全和权限系统

Deno 默认安全。与 Node.js 不同,Deno 脚本不能读取文件、访问网络或读取环境变量,除非你明确授予权限。

权限标志说明:

# Permission flags
--allow-read          Read file system
--allow-write         Write file system
--allow-net           Network access
--allow-env           Environment variables
--allow-run           Run subprocesses
--allow-ffi           Foreign function interface
--allow-sys           System information
--allow-all / -A      All permissions (dev only)

# No permissions — script is fully sandboxed
deno run sandboxed.ts

# Runtime will prompt for permission if not granted:
# Deno requests read access to "./config.json".
# Allow? [y/n/A] (y = allow, n = deny, A = allow all)

可以组合标志并将其限定到特定资源:

# Scoped permissions — only allow what is needed
deno run \
  --allow-read=./data,./config \
  --allow-write=./output \
  --allow-net=api.example.com:443,cdn.example.com \
  --allow-env=DATABASE_URL,API_KEY \
  server.ts

# Deny specific permissions (blocklist)
deno run \
  --allow-net --deny-net=evil.com \
  --allow-read --deny-read=/etc/passwd \
  app.ts

# Programmatic permission check
# const status = await Deno.permissions.query(
#   { name: "read", path: "./secrets" }
# );
# console.log(status.state); // "granted" | "denied" | "prompt"

一流的 TypeScript 支持

Deno 开箱即用支持 TypeScript,零配置。你可以直接运行 .ts 和 .tsx 文件。TypeScript 编译器内置在 Deno 二进制文件中。

通过 deno.json 配置 TypeScript:

// deno.json — TypeScript configuration
{
  "compilerOptions": {
    "strict": true,
    "jsx": "react-jsx",
    "jsxImportSource": "react",
    "lib": ["deno.window", "dom"],
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

# Type-check your code (not done by default for speed)
# deno check main.ts
# deno run --check main.ts

立即可用的 TypeScript 功能:

// Advanced TypeScript — works out of the box
type Result<T, E = Error> =
  | { ok: true; value: T }
  | { ok: false; error: E };

function safeParse<T>(json: string): Result<T> {
  try {
    return { ok: true, value: JSON.parse(json) as T };
  } catch (e) {
    return { ok: false, error: e as Error };
  }
}

interface Config {
  port: number;
  host: string;
  debug: boolean;
}

const result = safeParse<Config>('{"port":3000,"host":"localhost","debug":true}');
if (result.ok) {
  console.log("Server port:", result.value.port);
}

// Enums, generics, utility types — all native
type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

const partial: DeepPartial<Config> = { port: 8080 };

Deno 标准库

Deno 标准库(@std)是由 Deno 团队维护的高质量审查模块集合,通过 JSR 分发。

核心标准库模块:

// Deno Standard Library — import from jsr:@std
import { ensureDir, copy, walk } from "jsr:@std/fs";
import { join, resolve, basename } from "jsr:@std/path";
import { assertEquals, assertThrows } from "jsr:@std/assert";
import { delay } from "jsr:@std/async";
import { parse as parseFlags } from "jsr:@std/cli/parse-args";
import { encodeBase64, decodeBase64 } from "jsr:@std/encoding/base64";
import { crypto } from "jsr:@std/crypto";
import { serveDir } from "jsr:@std/http/file-server";

// File system utilities
await ensureDir("./output/logs");
await copy("./src", "./backup/src", { overwrite: true });

// Walk a directory tree
for await (const entry of walk("./src", { exts: [".ts"] })) {
  console.log("Found:", entry.path);
}

// Parse CLI flags
const args = parseFlags(Deno.args, {
  string: ["port", "host"],
  boolean: ["verbose"],
  default: { port: "3000", host: "localhost" },
});

// Encoding
const encoded = encodeBase64("Hello Deno");
console.log(encoded); // "SGVsbG8gRGVubw=="

使用 Deno.serve() 构建 HTTP 服务器

Deno 提供 Deno.serve() 作为创建 HTTP 服务器的主要 API,基于 hyper(Rust HTTP 库)构建。

带路由的基本 HTTP 服务器:

// server.ts — Basic HTTP server with routing
// Run: deno run --allow-net server.ts

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

  // JSON API endpoint
  if (url.pathname === "/api/health") {
    return Response.json({ status: "ok", uptime: Deno.uptime() });
  }

  // Dynamic route with URL params
  if (url.pathname.startsWith("/api/users/")) {
    const id = url.pathname.split("/").pop();
    return Response.json({ id, name: "User " + id });
  }

  // Query parameters
  if (url.pathname === "/api/search") {
    const query = url.searchParams.get("q") || "";
    return Response.json({ query, results: [] });
  }

  // HTML response
  if (url.pathname === "/") {
    return new Response("<h1>Welcome to Deno</h1>", {
      headers: { "Content-Type": "text/html" },
    });
  }

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

console.log("Server running at http://localhost:3000");

更完整的中间件模式服务器:

// Middleware pattern with Deno.serve()
type Handler = (req: Request) => Response | Promise<Response>;
type Middleware = (req: Request, next: Handler) => Response | Promise<Response>;

const logger: Middleware = async (req, next) => {
  const start = performance.now();
  const res = await next(req);
  const ms = (performance.now() - start).toFixed(1);
  console.log(req.method + " " + new URL(req.url).pathname + " " + res.status + " " + ms + "ms");
  return res;
};

const cors: Middleware = async (req, next) => {
  const res = await next(req);
  res.headers.set("Access-Control-Allow-Origin", "*");
  return res;
};

function compose(mws: Middleware[], h: Handler): Handler {
  return mws.reduceRight((next, mw) => (req) => mw(req, next), h);
}

const app = compose([logger, cors], () => {
  return Response.json({ message: "Hello from Deno!" });
});
Deno.serve({ port: 3000 }, app);

文件系统操作

Deno 通过 Deno 命名空间提供同步和异步文件系统 API,需要 --allow-read 和 --allow-write 权限。

常见文件系统操作:

// File system operations
// Run: deno run --allow-read --allow-write fs-demo.ts

// Read a text file
const content = await Deno.readTextFile("./config.json");
console.log(content);

// Write a text file
await Deno.writeTextFile("./output.txt", "Hello from Deno!");

// Read/write binary files
const bytes = await Deno.readFile("./image.png");
await Deno.writeFile("./copy.png", bytes);

// Create directory (recursive)
await Deno.mkdir("./output/nested/dir", { recursive: true });

// List directory contents
for await (const entry of Deno.readDir("./src")) {
  console.log(entry.name, entry.isFile ? "file" : "dir");
}

// File info (stat)
const info = await Deno.stat("./config.json");
console.log("Size:", info.size, "bytes");
console.log("Modified:", info.mtime);

// Remove files and directories
await Deno.remove("./temp.txt");
await Deno.remove("./temp-dir", { recursive: true });

// Rename / move
await Deno.rename("./old.txt", "./new.txt");

// Check if file exists
try {
  await Deno.stat("./maybe.txt");
  console.log("File exists");
} catch {
  console.log("File not found");
}

大文件的流式操作:

// Streaming with ReadableStream (web standard)
const bigFile = await Deno.open("./data.csv");
for await (const chunk of bigFile.readable) {
  console.log("Received", chunk.length, "bytes");
}

// Watch for file changes
const watcher = Deno.watchFs("./src");
for await (const event of watcher) {
  console.log("Event:", event.kind, event.paths);
}

使用 Deno 测试

Deno 包含内置测试运行器,支持测试定义、断言、异步测试、测试步骤、模拟、快照测试和代码覆盖率。

编写和组织测试:

// math.ts
export function add(a: number, b: number): number {
  return a + b;
}

export function divide(a: number, b: number): number {
  if (b === 0) throw new Error("Division by zero");
  return a / b;
}

// math_test.ts — Run: deno test math_test.ts
import { assertEquals, assertThrows } from "jsr:@std/assert";
import { add, divide } from "./math.ts";

Deno.test("add positive numbers", () => {
  assertEquals(add(2, 3), 5);
});

Deno.test("add negative numbers", () => {
  assertEquals(add(-1, -2), -3);
});

Deno.test("divide numbers", () => {
  assertEquals(divide(10, 2), 5);
});

Deno.test("divide by zero throws", () => {
  assertThrows(
    () => divide(10, 0),
    Error,
    "Division by zero"
  );
});

# Run tests with coverage
# deno test --coverage=./cov
# deno coverage ./cov --lcov > coverage.lcov

使用模拟和步骤的高级测试:

// Advanced testing with steps, mocking, and async
import { assertEquals } from "jsr:@std/assert";
import { stub, returnsNext } from "jsr:@std/testing/mock";

// Test steps — group related assertions
Deno.test("user CRUD operations", async (t) => {
  let userId: string;

  await t.step("create user", () => {
    userId = "user-123";
    assertEquals(typeof userId, "string");
  });

  await t.step("read user", () => {
    assertEquals(userId, "user-123");
  });

  await t.step("delete user", () => {
    userId = "";
    assertEquals(userId, "");
  });
});

// Mocking with stubs
Deno.test("mocking fetch", async () => {
  const fetchStub = stub(
    globalThis,
    "fetch",
    returnsNext([
      Promise.resolve(new Response('{"id":1}', { status: 200 })),
    ])
  );

  try {
    const res = await fetch("https://api.example.com/data");
    const data = await res.json();
    assertEquals(data.id, 1);
  } finally {
    fetchStub.restore();
  }
});

// Async test with resource sanitizers
Deno.test({
  name: "async database test",
  sanitizeResources: false,
  sanitizeOps: false,
  async fn() {
    // Test with open resources...
  },
});

使用 deno.json 配置任务

deno.json 文件是 Deno 项目的中央配置,替代 package.json 脚本、tsconfig.json 和导入映射。

完整的 deno.json 配置:

// deno.json — Complete project configuration
{
  "tasks": {
    "dev": "deno run --watch --allow-all src/main.ts",
    "start": "deno run --allow-net --allow-read --allow-env src/main.ts",
    "test": "deno test --allow-all --coverage=./coverage",
    "test:watch": "deno test --allow-all --watch",
    "check": "deno check src/main.ts",
    "lint": "deno lint",
    "fmt": "deno fmt",
    "build": "deno compile --output=dist/app src/main.ts",
    "bench": "deno bench --allow-all",
    "ci": "deno fmt --check && deno lint && deno check src/main.ts && deno test --allow-all"
  },
  "compilerOptions": {
    "strict": true,
    "jsx": "react-jsx",
    "jsxImportSource": "preact"
  },
  "fmt": {
    "semiColons": true,
    "singleQuote": true,
    "lineWidth": 100,
    "indentWidth": 2,
    "exclude": ["dist/", "coverage/"]
  },
  "lint": {
    "rules": {
      "tags": ["recommended"],
      "exclude": ["no-unused-vars"]
    },
    "exclude": ["dist/"]
  },
  "test": {
    "include": ["src/", "tests/"]
  },
  "lock": true
}

导入映射集中管理依赖:

// deno.json — Import map section
{
  "imports": {
    "@std/http": "jsr:@std/http@^1.0.0",
    "@std/assert": "jsr:@std/assert@^1.0.0",
    "@std/fs": "jsr:@std/fs@^1.0.0",
    "@std/path": "jsr:@std/path@^1.0.0",
    "@std/async": "jsr:@std/async@^1.0.0",
    "express": "npm:express@4",
    "zod": "npm:zod@^3.22",
    "drizzle-orm": "npm:drizzle-orm@^0.30",
    "@/": "./src/"
  }
}

// Now import with clean paths:
// import { assertEquals } from "@std/assert";
// import { z } from "zod";
// import { db } from "@/lib/database.ts";

npm 兼容性

Deno 通过 npm: 说明符原生支持 npm 包。包被全局下载和缓存,默认不创建 node_modules 目录。

在 Deno 中使用 npm 包:

// Using npm packages in Deno
import express from "npm:express@4";
import { z } from "npm:zod";
import chalk from "npm:chalk@5";
import _ from "npm:lodash";

// Zod schema validation
const UserSchema = z.object({
  name: z.string().min(1),
  email: z.string().email(),
  age: z.number().int().positive(),
});

type User = z.infer<typeof UserSchema>;

const result = UserSchema.safeParse({ name: "Bob", email: "bob@test.com", age: 25 });
if (result.success) {
  console.log(chalk.green("Valid user: " + result.data.name));
}

// Express server in Deno
const app = express();
app.get("/", (_req, res) => {
  res.json({ runtime: "deno", framework: "express" });
});
app.listen(3000, () => {
  console.log("Express on Deno at http://localhost:3000");
});

// Run: deno run --allow-net --allow-read --allow-env server.ts

通过 node: 说明符使用 Node.js 内置模块:

// Node.js built-in modules via node: specifier
import { readFileSync, writeFileSync } from "node:fs";
import { join, resolve } from "node:path";
import { createHash, randomUUID } from "node:crypto";
import { EventEmitter } from "node:events";
import { Buffer } from "node:buffer";
import { setTimeout } from "node:timers/promises";

// These work identically to Node.js
const configPath = join(".", "config.json");
const data = readFileSync(configPath, "utf-8");
const hash = createHash("sha256").update(data).digest("hex");
console.log("Hash:", hash);

// EventEmitter
const emitter = new EventEmitter();
emitter.on("data", (msg: string) => console.log("Received:", msg));
emitter.emit("data", "hello from node:events");

// Buffer operations
const buf = Buffer.from("Hello Deno", "utf-8");
console.log(buf.toString("base64")); // SGVsbG8gRGVubw==

使用 Deno Deploy 部署

Deno Deploy 是专为 Deno 构建的全球分布式边缘托管平台,在 35+ 个区域运行代码。

设置 Deno Deploy 项目:

# Deploy to Deno Deploy

# 1. Install deployctl CLI
deno install -A jsr:@deno/deployctl

# 2. Create main.ts for edge deployment
# Deno.serve((req: Request) => {
#   return new Response("Hello from the edge!");
# });

# 3. Deploy from CLI
deployctl deploy --project=my-app main.ts

# 4. Or connect GitHub for auto-deploy:
#    - Go to dash.deno.com
#    - Create project > Link to GitHub repo
#    - Set entrypoint to main.ts
#    - Every push to main triggers deployment

# Docker deployment (alternative)
# FROM denoland/deno:latest
# WORKDIR /app
# COPY . .
# RUN deno cache main.ts
# EXPOSE 3000
# CMD ["run", "--allow-net", "--allow-read", "--allow-env", "main.ts"]

Deno Deploy 提供 KV 存储、定时任务和 BroadcastChannel:

// Deno Deploy features: KV, Cron, BroadcastChannel

// Deno KV — distributed key-value storage
const kv = await Deno.openKv();

// Store a value
await kv.set(["users", "alice"], { name: "Alice", visits: 0 });

// Read a value
const entry = await kv.get(["users", "alice"]);
console.log(entry.value); // { name: "Alice", visits: 0 }

// Atomic transactions
await kv.atomic()
  .check(entry) // Ensure no concurrent modification
  .set(["users", "alice"], { name: "Alice", visits: 1 })
  .commit();

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

// Deno Cron — scheduled tasks
Deno.cron("cleanup", "0 0 * * *", async () => {
  console.log("Running daily cleanup...");
  // Delete expired entries
});

// BroadcastChannel — cross-isolate messaging
const channel = new BroadcastChannel("updates");
channel.onmessage = (e) => console.log("Update:", e.data);

Fresh 框架

Fresh 是 Deno 的官方全栈 Web 框架,使用岛屿架构进行选择性客户端水合,默认在服务器端渲染页面。

创建和理解 Fresh 项目:

# Create a Fresh project
deno run -A -r https://fresh.deno.dev my-fresh-app
cd my-fresh-app
deno task start

# Fresh project structure:
# my-fresh-app/
#   routes/           File-based routes
#     index.tsx       GET / (server-rendered)
#     about.tsx       GET /about
#     api/joke.ts     GET /api/joke (API route)
#     [name].tsx      GET /:name (dynamic route)
#     _middleware.ts  Middleware for all routes
#   islands/          Interactive components (client JS)
#     Counter.tsx     Ships JavaScript to the browser
#   components/       Server-only components (no JS shipped)
#   static/           Static files
#   fresh.gen.ts      Auto-generated manifest
#   deno.json         Project config

// routes/index.tsx — Server-rendered page
// export default function Home() {
//   return (
//     <div>
//       <h1>Welcome to Fresh</h1>
//       <Counter start={0} />
//     </div>
//   );
// }

Fresh 岛屿架构的交互组件:

// islands/Counter.tsx — Interactive island component
// Only this component ships JavaScript to the browser
import { useSignal } from "@preact/signals";

interface CounterProps {
  start: number;
}

export default function Counter(props: CounterProps) {
  const count = useSignal(props.start);
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => count.value--}>-1</button>
      <button onClick={() => count.value++}>+1</button>
    </div>
  );
}

// routes/api/joke.ts — API route
// import { FreshContext } from "$fresh/server.ts";
// const JOKES = ["Why do programmers prefer dark mode?...",];
// export const handler = (_req: Request, _ctx: FreshContext) => {
//   const joke = JOKES[Math.floor(Math.random() * JOKES.length)];
//   return new Response(JSON.stringify({ joke }), {
//     headers: { "Content-Type": "application/json" },
//   });
// };

Deno 与 Node.js:详细对比

Deno 和 Node.js 都是基于 V8 的 JavaScript 运行时,但在设计理念、安全模型和开发体验上有显著差异。

功能对比:

FeatureDenoNode.js
LanguageRust + V8C++ + V8
TypeScriptNative, zero configVia tsx/ts-node (native in v22+)
SecuritySandboxed by defaultUnrestricted by default
Package ManagerBuilt-in (deno add)npm / yarn / pnpm
Module SystemESM only (CJS via compat)CJS + ESM
FormatterBuilt-in (deno fmt)Prettier (external)
LinterBuilt-in (deno lint)ESLint (external)
Test RunnerBuilt-in (deno test)Built-in (node --test) / Jest
npm Compatibility~95%+ via npm: specifier100% native
Web APIsExtensive (fetch, Streams, etc.)Partial (fetch added in v18)
Edge HostingDeno Deploy (built-in)Vercel / Cloudflare (external)
Ecosystem Maturity5+ years, growing15+ years, massive
Config FilesSingle deno.jsonpackage.json + tsconfig + .eslintrc + ...

选择 Deno:新项目、安全敏感应用、边缘部署、需要内置工具的团队。选择 Node.js:遗留项目、需要特定 Node.js 功能的框架、已有 Node.js 工作流的团队。

最佳实践

  • 始终使用最小所需权限。生产环境中不要使用 --allow-all。将权限限定到特定路径和主机。
  • 在导入映射中固定依赖版本。使用确切版本以实现可重现的构建。
  • 使用 deno.lock 锁定依赖版本。运行 deno cache --lock=deno.lock 验证完整性。
  • 优先使用 Deno 原生 API,而非 Node.js 兼容模块,以获得更好的性能。
  • 在 CI 管道中运行 deno fmt 和 deno lint。它们快速、有主见且团队一致。
  • 使用 Deno.test 的步骤进行集成测试。步骤提供清晰的输出和独立的通过/失败状态。
  • 部署到 Deno Deploy 以获得边缘性能。尽可能使用 Deno KV 代替外部数据库。
  • 使用 deno compile 编译独立二进制文件,用于 CLI 工具和不需要安装 Deno 的内部工具。
# Recommended CI pipeline for Deno projects
# .github/workflows/ci.yml
#
# name: CI
# on: [push, pull_request]
# jobs:
#   test:
#     runs-on: ubuntu-latest
#     steps:
#       - uses: actions/checkout@v4
#       - uses: denoland/setup-deno@v2
#         with:
#           deno-version: v2.x
#       - run: deno fmt --check
#       - run: deno lint
#       - run: deno check src/main.ts
#       - run: deno test --allow-all --coverage=cov
#       - run: deno coverage cov --lcov > coverage.lcov

常见问题

Deno 已经准备好用于生产了吗?

是的。Deno 已被 Slack、Netlify、Supabase 和 GitHub 等公司在生产中使用。运行时自 1.0 以来一直稳定,Deno 2 巩固了向后兼容性和 npm 支持。

可以在 Deno 中使用 npm 包吗?

可以。Deno 使用 npm: 说明符原生支持 npm 包。大多数 npm 包无需修改即可工作。也可以使用 package.json 和 node_modules。

Deno 权限系统如何工作?

Deno 默认在沙箱中运行脚本。通过标志显式授予权限:--allow-read 用于文件系统,--allow-net 用于网络,--allow-env 用于环境变量。权限可限定到特定路径和主机。

需要配置 TypeScript 才能在 Deno 中使用吗?

不需要。Deno 原生运行 TypeScript,无需任何 tsconfig.json 或构建步骤。TypeScript 编译器内置在 Deno 二进制文件中。

Deno 和 Bun 有什么区别?

两者都是现代 JavaScript 运行时。Deno 使用 V8,专注于安全性和 Web 标准。Bun 使用 JavaScriptCore,专注于执行速度和 Node.js 兼容性。

Deno Deploy 是什么,费用多少?

Deno Deploy 是全球分布式边缘托管平台。免费套餐包括每天 10 万请求和 1 GB 出站传输。Pro 套餐每月 20 美元。

可以将现有 Node.js 项目迁移到 Deno 吗?

可以。Deno 2 提供强大的 Node.js 兼容性。增量迁移:添加 deno.json,更新导入使用 node: 和 npm: 前缀,替换 npm 脚本为 Deno 任务。

Fresh 框架是什么?

Fresh 是 Deno 的官方 Web 框架,使用岛屿架构。默认在服务器端渲染页面,仅为交互组件发送 JavaScript。支持文件系统路由和 JSX/TSX。

𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

{ }JSON FormatterJSON Validator

相关文章

Bun 完全指南:全能 JavaScript 运行时

掌握 Bun 运行时,包括包管理器、打包器、测试运行器、HTTP 服务器、SQLite 与 Shell 脚本。

SWC 完全指南:Rust 驱动的超快 JavaScript 编译器

掌握 SWC 超快编译,包括配置、转换、压缩、框架集成与从 Babel 迁移。

esbuild 完全指南:最快的 JavaScript 打包工具

掌握 esbuild 超快打包,包括 CLI、JavaScript API、插件、加载器、压缩与生产优化。