Deno Introduction-A Modern Alternative to Node.js

I focus on the long-term foundations of computer science, software engineering, and emerging technologies.covering computer science, AI, semiconductors, quantum computing, and future engineering.
Search for a command to run...

I focus on the long-term foundations of computer science, software engineering, and emerging technologies.covering computer science, AI, semiconductors, quantum computing, and future engineering.
No comments yet. Be the first to comment.
The content covers the three basics of HTML/CSS/JS/TS, modular development, mainstream frameworks (Vue, React, Angular, Svelte), build tools, browser plug-in development, Node.js backend practice, Next.js/Nest.js and other popular technologies.
React Query is a powerful state management library designed for handling data fetching, caching, and updating, particularly suited for API interactions. It offers advanced features such as automatic caching, offline state management, data expiration,...
Progressive Web Apps (PWAs) utilize offline storage strategies to provide an offline experience, enabling access to some content even when the network is unavailable. The two primary offline storage t

WebGL (Web Graphics Library) is a JavaScript API that enables hardware-accelerated 3D graphics rendering in any compatible web browser without the need for plugins. Based on the OpenGL standard, it in

React Query is a powerful state management library designed for handling data fetching, caching, and updating, particularly suited for API interactions. It offers advanced features such as automatic caching, offline state management, data expiration,...

Generics In TypeScript, generics are a powerful tool that allow us to write reusable components capable of adapting to multiple types. 1. Generic Constraints Generics can be constrained to a specific type or interface, ensuring that the types passed ...

Deno, as a modern alternative to Node.js, offers numerous improvements and innovations, particularly in security, module systems, and developer experience. Although still in development, Deno is a compelling choice for developers seeking a simple, secure, and modern JavaScript/TypeScript development environment. As its community continues to grow, Deno’s potential and influence are expected to expand further.
Built-in Security Model: Deno enforces strict permission controls, requiring explicit permissions for actions like file read/write or network access.
TypeScript Support: Deno natively supports TypeScript, providing enhanced type checking and a better development experience.
ES Modules: Deno uses URLs or import maps for module imports, differing from Node.js’s CommonJS module system.
deno run: Executes a single file.
deno test: Runs tests.
deno fmt: Formats code.
deno lint: Checks code style.
Deno’s configuration is primarily managed through the deno.json file, which allows customization of runtime behavior. Environment variables mainly affect Deno’s global configuration, such as logging levels or cache directories.
Deno Configuration File (deno.json)
The configuration file typically includes the following sections:
permissions: Defines runtime permissions.
importMap: Configures module import mappings.
compilerOptions: TypeScript compiler options.
lintRules: Linting rules (if using deno-lint).
watch: Monitors file changes and automatically re-runs.
reload: Automatically reloads modules.
{
"permissions": {
"env": true,
"net": ["*"],
"read": ["./data"],
"write": ["./output"]
},
"importMap": {
"imports": {
"lodash": "https://cdn.skypack.dev/lodash@4.17.21",
"my-local-module": "./src/my-local-module.ts"
}
},
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"lib": ["dom", "deno.ns"],
"strict": true
},
"lintRules": {
// ...
},
"watch": true,
"reload": {
"enabled": true,
"include": ["./src"]
}
}
DENO_DIR: Specifies the configuration, cache, and download directory, defaulting to ~/.deno.
DENO_AUTH_TOKEN: Authentication token for accessing private modules.
DENO_LOGGING_LEVEL: Controls logging level, e.g., debug, info, warn, error.
DENO_CACHE: Custom cache directory.
DENO.land_proxy: Proxy settings for accessing deno.land.
DENO_NO_COLOR: Disables colored output if set.
# Linux/MacOS
export DENO_DIR=/path/to/custom/deno/dir
export DENO_LOGGING_LEVEL=debug
# Windows
set DENO_DIR=%USERPROFILE%\custom\deno\dir
set DENO_LOGGING_LEVEL=debug
Note that not all configuration options can be set via environment variables; most configurations are defined in the deno.json file. Deno’s permissions are typically specified at runtime via command-line flags, not through configuration files or environment variables. For example: deno run --allow-read=./data your_script.ts.
Creating an HTTP server in Deno is straightforward using the built-in std/http library.
// server.ts
import { serve } from "https://deno.land/std/http/server.ts";
const s = serve({ port: 8000 });
console.log("Server is running on http://localhost:8000");
for await (const req of s) {
req.respond({ status: 200, body: "Hello, World!\n" });
}
Code Breakdown:
Import the serve Function: import { serve } from "https://deno.land/std/http/server.ts"; imports the serve function from Deno’s standard library to create an HTTP server.
Start the Server: const s = serve({ port: 8000 }); creates and starts a server listening on port 8000. s is an iterable object representing each incoming request.
Log Server Info: console.log("Server is running on http://localhost:8000"); informs users that the server is running and provides the access URL.
Handle Requests: for await (const req of s) is an async iterator that waits for and processes each incoming HTTP request. req is a ServerRequest instance containing request details.
Respond to Requests: req.respond({ status: 200, body: "Hello, World!\n" }); sends a response to the client with a 200 status code and a body of "Hello, World!\n".
Run the Server: In the terminal, run the script with deno run --allow-net server.ts. The --allow-net flag is required to allow network access.
Fetching remote data in Deno typically uses the fetch API:
// fetch_data.ts
import { assert } from "https://deno.land/std/testing/asserts.ts";
import { json as parseJson } from "https://deno.land/std/io/ioutil.ts";
async function fetchData(url: string) {
const response = await fetch(url);
assert(response.ok, `Failed to fetch data: ${response.statusText}`);
const data = await parseJson(await response.text());
console.log(data);
}
// Example URL, replace with your desired data source
const remoteDataURL = "https://jsonplaceholder.typicode.com/todos/1";
fetchData(remoteDataURL);
Code Breakdown:
assert ensures the HTTP request succeeds.
parseJson converts received text to a JSON object.
fetchData Function:fetch(url) asynchronously sends an HTTP GET request to the specified URL.
response.ok checks if the HTTP status code is in the 200-299 range, indicating success.
response.text() retrieves the response body as text.
parseJson(text) parses the text into a JSON object.
console.log(data) logs the parsed data.
fetchData:fetchData(remoteDataURL) calls the function with an example URL to fetch remote data.deno run --allow-net fetch_data.ts. The --allow-net flag is required for network access.// file_operations.ts
import { readTextFile, writeTextFile } from "https://deno.land/std/fs/mod.ts";
// Read a file
const content = await readTextFile("example.txt");
console.log(content);
// Write to a file
const newContent = "This is new content.";
await writeTextFile("example.txt", newContent);
// http_server.ts
import { serve } from "https://deno.land/std/http/server.ts";
const s = serve({ port: 8000 });
console.log("Server is running on http://localhost:8000");
for await (const req of s) {
req.respond({ status: 200, body: "Hello, World!\n" });
}
Deno uses async/await syntax for asynchronous operations, making code cleaner and easier to understand.
// async_example.ts
import { delay } from "https://deno.land/std/async/mod.ts";
async function asyncTask() {
console.log("Task started...");
await delay(1000); // Delay for 1 second
console.log("Task completed.");
}
asyncTask();
// async_file.ts
import { ensureDir, readTextFile, writeTextFile } from "https://deno.land/std/fs/mod.ts";
import { delay } from "https://deno.land/std/async/mod.ts";
async function asyncFileOps() {
try {
await ensureDir("output"); // Ensure directory exists
const content = await readTextFile("input.txt");
console.log("Read content:", content);
const newContent = "New content";
await writeTextFile("output/output.txt", newContent);
console.log("Wrote new content to output file.");
await delay(2000); // Delay for 2 seconds
console.log("Finished async operations.");
} catch (err) {
console.error("An error occurred:", err);
}
}
asyncFileOps();
Deno’s module system is based on ES Modules, allowing code import and export via URLs. Deno’s standard library provides useful modules for file system operations, networking, HTTP servers, JSON processing, encryption, and more.
// import_std.ts
import { readTextFile } from "https://deno.land/std/fs/mod.ts";
import { serve } from "https://deno.land/std/http/server.ts";
// Read a file using readTextFile
const content = await readTextFile("example.txt");
console.log(content);
// Create an HTTP server
const s = serve({ port: 8000 });
console.log("Server is running on http://localhost:8000");
for await (const req of s) {
req.respond({ status: 200, body: "Hello, World!\n" });
}
// my_module.ts
export function add(a: number, b: number): number {
return a + b;
}
// Import in another file
// import_ts.ts
import { add } from "./my_module.ts";
console.log(add(2, 3)); // Outputs 5
// json_example.ts
import { readTextFile } from "https://deno.land/std/fs/mod.ts";
import { json as parseJson } from "https://deno.land/std/json/mod.ts";
const jsonData = await readTextFile("data.json");
const data = parseJson(jsonData);
console.log(data);
// net_example.ts
import { connect } from "https://deno.land/std/net/tcp.ts";
const conn = await connect({ hostname: "localhost", port: 8000 });
conn.write(new TextEncoder().encode("GET / HTTP/1.1\r\nHost: localhost:8000\r\n\r\n"));
const response = new TextDecoder().decode(await Deno.readAll(conn));
console.log(response);
conn.close();
// third_party_module.ts
import { log } from "https://x.nest.land/log@0.1.0/mod.ts";
log.info("This is an info message");
Deno’s standard library and third-party modules are typically imported via HTTPS URLs, providing version control and security. deno.land is a module registry similar to npm but designed for Deno. x.nest.land is another Deno module repository hosting community-maintained modules.
Deno supports WebSocket through its standard library or third-party libraries. The following example uses the ws third-party library, popular for both Deno and Node.js.
Install the ws library:
deno install -A -f --unstable --name deno_ws https://deno.land/x/ws@v1.1.0/mod.ts
Create a WebSocket server to listen for client connections and send messages to connected clients.
// server.ts
import { Server } from "deno_ws/mod.ts";
const server = new Server({ port: 8080 });
server.on("connection", (socket) => {
console.log("Client connected");
socket.on("message", (message) => {
console.log(`Received message => ${message}`);
socket.send(`You sent -> ${message}`);
});
socket.on("close", () => {
console.log("Client disconnected");
});
});
console.log("WebSocket server is running on ws://localhost:8080");
Create a WebSocket client to connect to the server and send/receive messages.
// client.ts
import { connect } from "deno_ws/mod.ts";
const socket = connect("ws://localhost:8080");
socket.on("open", () => {
console.log("Connected to WebSocket server");
socket.send("Hello, Server!");
});
socket.on("message", (message) => {
console.log(`Received from server: ${message}`);
});
socket.on("close", () => {
console.log("Connection closed");
});
Open two terminal windows.
In the first window, run the server:
deno run --allow-net server.ts
In the second window, run the client:
deno run --allow-net client.ts
Server-Side:
Imports the Server class and creates an instance listening on port 8080.
Handles new client connections with the connection event, logging and setting up a message handler.
Responds to each received message with a confirmation message.
Logs when a client disconnects via the close event.
Client-Side:
Uses the connect function to connect to the server’s URL.
Sets an open event handler to send a message when the connection is established.
Sets a message event handler to receive and log server messages.
Sets a close event handler to log connection closure.
Deno uses try/catch for error handling, supporting asynchronous error handling.
// error_handling.ts
import { readFile } from "https://deno.land/std/fs/mod.ts";
try {
const data = await readFile("non_existent_file.txt");
} catch (error) {
if (error instanceof Deno.errors.NotFound) {
console.error("File not found:", error);
} else {
throw error; // Re-throw unhandled errors
}
}
Debugging in Deno can be done using console.log, console.error, and the debugger statement with an IDE or browser developer tools.
// debug.ts
function debugFunction(value) {
debugger; // Pauses execution, allowing context inspection in a debugger
console.log("Debugging value:", value);
}
debugFunction("Debug me");
Avoid Unnecessary Computations: Compute values only when needed, avoiding premature calculations.
Use Asynchronous Operations: For I/O-intensive tasks, use async operations to avoid blocking the main thread.
Cache Results: Cache results of repetitive computations.
Leverage Type Checking: TypeScript’s type system helps prevent runtime errors and improves code quality.
Restrict Permissions: Deno’s permission model allows precise control over code access, minimizing resource waste.
Here’s an optimization example using deno.cache to cache imported modules:
// optimized_import.ts
import { cache } from "https://deno.land/x/deno.land_std@0.125.0/cache/mod.ts";
const cachedModule = await cache(
"https://deno.land/x/your_module@latest",
".cache",
);
// Import from cache
import * as mod from `${cachedModule}/mod.ts`;