Deno is a simple modern secure runtime for writing applications using JavaScript and TypeScript that uses the V8 engine built in Rust.
This is not an article that explains what Deno is. However, I can help if you need to know more about Deno. Check out this article: What’s Deno, and how it is different from Node.js?
And you can also check out the Deno repository if you are interested in future developments.
Now, Node has grown powerful and popular in the past few years. There are also a few popular Node projects that have cropped up, which are called dependencies. Since the birth of Deno, there have been a lot of doubts about how to do the same things we do in Node in Deno.
I will go over a few of the most popular ones in Node and show you its alternatives in Deno.
Aleph.js is a React Framework in Deno. Yeah, that’s it. Just as Next.js is in Node. Next.js for Node provides all the features you need for production using React. It lets you build server-side rendering, automatic code-splitting, static exporting options, easy production builds, and also static web applications.
Unlike Next.js, Aleph.js doesn’t use or need a bundler since it uses the ESM(ECMAScript Module) import syntax. Each module imported is just compiled once and cached:
import React from "https://esm.sh/react@17.0.1"
import Logo from "../components/logo.tsx"
export default function Home() {
return (
<div>
<Logo />
<h1>Hello World!</h1>
</div>
)
}
Other advanced features Aleph.js provides are Asynchronous Import, Custom 404
Page, Custom Loading Page, useDeno
Hook, and more.
Express.js is very popular for its open, free, or liberal minimalist web framework for Node. Its philosophy is to deliver a small, fast tooling for HTTP servers, making it an awesome option for SPAs, websites, hybrid, or public HTTP APIs. You can just craft your own framework using Express.js anyway. Another great thing is its robust routing system, which efficiently responds to clients requests, and few selection of HTTP helpers.
Unlike Express.js, Opine is focused on high performance, content negotiation (which is awesome when returning responses based on a type of request), robust routing, and support for HTTP proxy middleware (which is useful in Authorization, Load balancing, Logging, etc). The future is bright for Opine!
import opine from "../../mod.ts";
const app = opine();
app.get("/", function (req, res) {
res.send("Hello Deno!");
});
const server = app.listen();
const address = server.listener.addr as Deno.NetAddr;
console.log(`Server started on ${address.hostname}:${address.port}`);
I really love how content negotiation is handled in Opine, making you deal with each type of formatting at a glance:
import { opine } from "../../mod.ts";
import { users } from "./db.ts";
import type { Request, Response } from "../../src/types.ts";
const app = opine();
app.get("/", (req, res) => {
res.format({
html() {
res.send(
`<ul>${users.map((user) => `<li>${user.name}</li>`).join("")}</ul>`,
);
},
text() {
res.send(users.map((user) => ` - ${user.name}\n`).join(""));
},
json() {
res.json(users);
},
});
});
Passport.js simply helps in handling authentication in your Node server. It serves as a middleware, extremely pliable and modular. It is widely used in any Express.js-based web application. It provides support for a set of authentication strategies(username and password, Facebook, Twitter, etc).
Unlike Passport.js, the main focus of Onyx is keeping code clean and systematic. It helps you streamline your authentication strategies without importing, as you would do in Passport.js.
Just as you would apply Passport.js as a middleware, the same goes for Onyx:
import { Router } from '../deps.ts';
import { onyx } from '../deps.ts';
import User from './models/userModels.ts';
const router = new Router();
// invoke onyx.authenticate with the name of the strategy, invoke the result with context
router.post('/login', async (ctx) => {
await (await onyx.authenticate('local'))(ctx);
if (await ctx.state.isAuthenticated()) {
const { username } = await ctx.state.getUser();
ctx.response.body = {
success: true,
username,
isAuth: true,
};
} else {
const message = ctx.state.onyx.errorMessage || 'login unsuccessful';
ctx.response.body = {
success: false,
message,
isAuth: false,
};
}
});
Pretty straightforward to setup in your server file. It’s the same process you would do in Node:
import { Application, send, join, log } from '../deps.ts';
import { Session } from '../deps.ts';
// Import in onyx and setup
import { onyx } from '../deps.ts';
import './onyx-setup.ts';
// Server Middlewares
import router from './routes.ts';
// SSR
import { html, browserBundlePath, js } from './ssrConstants.tsx';
const port: number = Number(Deno.env.get('PORT')) || 4000;
const app: Application = new Application();
// session with Server Memory
// const session = new Session({ framework: 'oak' });
// session with Redis Database
const session = new Session({
framework: 'oak',
store: 'redis',
hostname: '127.0.0.1',
port: 6379,
});
// Initialize Session
await session.init();
app.use(session.use()(session));
// Initialize onyx after session
app.use(onyx.initialize());
Redis is a popular in-memory data structure server often known and used for caching, as well as database and message brokering. It is super fast with amazingly high throughput.
In Node, node-redis has been a high performant Redis client, which is entirely asynchronous.
deno-redis is the implementation of Redis client for Deno:
import { connect } from "https://deno.land/x/redis/mod.ts";
const redis = await connect({
hostname: "127.0.0.1",
port: 6379
});
const ok = await redis.set("hoge", "fuga");
const fuga = await redis.get("hoge");
Nodemon is a command-line interface (CLI) that watches the file system for any changes in your Node project and automatically restarts the process/server. This helps to avoid manually restarting your server to see changes already made.
In Deno, we have Denon. No difference to nodemon. All you have to do is replace deno
with the word denon
.
denon run app.ts
The Websocket API opens a two-way interactive communication between the client and the server. Basically, there is a persistent connection between a client and a server so that both can send data at any time. The ws library was built as a client and server implementation for your Node project.
Fortunately, we have deno websocket — a library that’s the same as ws but for Deno.
Usage on the server side is quite similar to what would happen with any Node project:
import { WebSocket, WebSocketServer } from "https://deno.land/x/websocket@v0.0.5/mod.ts";
const wss = new WebSocketServer(8080);
wss.on("connection", function (ws: WebSocket) {
ws.on("message", function (message: string) {
console.log(message);
ws.send(message)
});
});
Same for the client side:
import { WebSocket } from "https://deno.land/x/websocket@v0.0.5/mod.ts";
const endpoint = "ws://127.0.0.1:8080";
const ws: WebSocket = new WebSocket(endpoint);
ws.on("open", function() {
console.log("ws connected!");
});
ws.on("message", function (message: string) {
console.log(message);
});
ws.send("something");
Next we have cors, a Node package providing support as a middleware which can be used to enable CORS with a variety of options.
A simple usage to enable all cors requests in an Express.js application can be seen below:
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
In Deno, we would do same in Opine. For example:
import { opine, serveStatic } from "https://deno.land/x/opine/mod.ts";
import { opineCors } from "../../mod.ts";
const app = opine();
app.use(opineCors()); // Enable CORS for All Routes
app
.use(serveStatic(`${Deno.cwd()}/examples/opine/static`))
.get("/products/:id", (_req, res) => {
res.json({msg: 'This is CORS-enabled for all origins!'});
})
.listen(
{ port: 8000 },
() => console.info("CORS-enabled web server listening on port 8000"),
);
Both are similar libraries used in hashing passwords. Bcrypt, designed by Niel Provos, is a password-hashing function that is mostly used on passwords. What it basically does is generate a hash from the password and save it.
While we have had Bcrypt for Node, we now have BCrypt, but for Deno. Usage in Deno is still almost as it is done in Node:
import * as bcrypt from "https://deno.land/x/bcrypt/mod.ts";
const hash = await bcrypt.hash("test");
// To check a password
const result = await bcrypt.compare("test", hash);
In Node, you can create cross-platform desktop applications using Electron. In Deno, we now have WebView. It is also used to create GUIs for cross platform desktop applications:
import { WebView } from "https://deno.land/x/webview/mod.ts";
const html = `
<html>
<body>
<h1>Hello from deno</h1>
</body>
</html>
`;
await new WebView({
title: "Local webview_deno example",
url: `data:text/html,${encodeURIComponent(html)}`,
height: 600,
resizable: true,
debug: true,
frameless: false,
}).run();
MongoDB is popular, scalable, and flexible. It is a document-based database mostly and widely used in the JavaScript ecosystem.
And yes, it is now possible to have MongoDB in Deno:
import { MongoClient } from "https://deno.land/x/mongo@v1.0.0/mod.ts";
const client = new MongoClient();
client.connectWithUri("mongodb://localhost:27017");
// Defining schema interface
interface UserSchema {
_id: { $oid: string };
username: string;
password: string;
}
const db = client.database("test");
const users = db.collection<UserSchema>("users");
// insert
const insertId = await users.insertOne({
username: "user1",
password: "pass1",
});
// insertMany
const insertIds = await users.insertMany([
{
username: "user1",
password: "pass1",
},
{
username: "user2",
password: "pass2",
},
]);
// findOne
const user1 = await users.findOne({ _id: insertId });
// find
const all_users = await users.find({ username: { $ne: null } });
// find by ObjectId
const user1_id = await users.findOne({ _id: "idxxx" });
SMTP serves as the main transport in Nodemailer for sending messages. Now available in Deno as Deno SMTP:
import { SmtpClient } from "https://deno.land/x/smtp/mod.ts";
const client = new SmtpClient();
await client.connect({
hostname: "smtp.163.com",
port: 25,
username: "username",
password: "password",
});
await client.send({
from: "mailaddress@163.com",
to: "to-address@xx.com",
subject: "Mail Title",
content: "Mail Content,maybe HTML",
});
await client.close();
npm in Node is the popular package management tool that has been in existence for a long time now, and it is awesome that we have an alternative to it in Deno with Trex. It comes with a lot of options, much like npm. Never forget that packages are cached and only one file is generated.
There are a lot of these Deno alternatives, which are currently still in development. We still have:
In this article, we’ve gone over some of the Deno alternatives to popular Node projects used during development. We believe Deno is still growing, and it’ll be great to know the current alternatives already available if you will be venturing further into the Deno world.
If you feel I skipped a popular Node alternative, you can drop them as a reply.
Deploying a Node-based web app or website is the easy part. Making sure your Node instance continues to serve resources to your app is where things get tougher. If you’re interested in ensuring requests to the backend or third-party services are successful, try LogRocket.
LogRocket lets you replay user sessions, eliminating guesswork around why bugs happen by showing exactly what users experienced. It captures console logs, errors, network requests, and pixel-perfect DOM recordings — compatible with all frameworks.
LogRocket's Galileo AI watches sessions for you, instantly identifying and explaining user struggles with automated monitoring of your entire product experience.
LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. Start monitoring for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowThis guide explores how to use Anthropic’s Claude 4 models, including Opus 4 and Sonnet 4, to build AI-powered applications.
Which AI frontend dev tool reigns supreme in July 2025? Check out our power rankings and use our interactive comparison tool to find out.
Learn how OpenAPI can automate API client generation to save time, reduce bugs, and streamline how your frontend app talks to backend APIs.
Discover how the Interface Segregation Principle (ISP) keeps your code lean, modular, and maintainable using real-world analogies and practical examples.
One Reply to "Deno alternatives to popular Node projects"
Is there an alternative to Node-Red?