Nexpress is an implementation of an express-like web framework with most of the basic features that express offers but in a simpler way.
This source code isn't ready for production use. This implementation of a web framework is just for learning purposes and doesn't assure reliability.
See full example in the app directory
import Nexpress from '../nexpress/index.js';
const app = new Nexpress();
app.use((req, res, next) => {
console.log(new Date(), req.method, req.path);
next();
})
app.get("/", (req, res, next) => {
res.send("Index");
})
app.get("/page1", (req, res, next) => {
res.send("Page 1");
})
app.use((req, res, next) => {
res.send("Global Catcher");
})
app.listen(3000, () => console.log("Listening on port 3000"));
import Router from "../nexpress/handlers/Router.js";
const indexRouter = new Router();
indexRouter.route("/login")
.get(getLoginForm)
.post(postLoginForm)
indexRouter.all("/404", (req, res, next) => {
res.send("Not Found");
})
app.use("/", indexRouter);
The project is implemented in ES6 Modules
, using TypeScript to obtain strict typing. The behaviour of the routers and objects is maintained to obtain the maximum flexibility possible.
The project heavily relys on the built-in node:http
module. The number of dependencies is reduced to only one dependency that can be removed in the future.
I built this project from an OOP point of view. The project mainly implements Chain of Responsibility design pattern (CoR) to implement the middleware behaviour.
The building unit of the system is the RequestHandler
class.
A RequestHandler
's logic can be a single function to be executed, so it becomes a Middleware
. Or the logic of the RequestHandler
can be a bunch of RequestHandlers
executed in order, in this case it becomes a HandlerSequence
.
The HandlerSequence
class itself has two child classes:
Router
: Allows nesting routers, request handlers and paths.SingleRoute
: Works for only one path. It can be created by callingrouter.route(PATH)
.
The App
class is responsible for creating the application and the root router. The application itself can behave like a router by passing stuff to the root router.
The use of OOP in this case may seem as an overengineering solution to a simple problem, but it is for learning purpose.
- Allows nesting routes unlimitedly.
- Supports path prefixing and path exact matching, with handling corner cases like trailing slashes.
- Able to modularize and create a good-looking file structure.
- Support for Dynamic URLs
- Support for connect-like middleware functions
- Support for template engines