Hacker News new | ask | show | jobs
by hombre_fatal 774 days ago
That still doesn't address the main difference between Express and Koa.

In Express, the route handlers send the response directly so your middleware can only be "beforeware".

In Koa, the route handlers update a response object that bubbles back up the stack before it's sent, so you can write both beforeware and afterware (so, real middleware).

For example:

    app.use(async (ctx, next) => {
        console.log('Request is going down', ctx.request.body)
        await next()
        console.log('Response is coming up', ctx.response.body)
    })
2 comments

Sure, but that doesn’t seem very relevant to this thread. Also in express there are certainly ways to do what you say, for instance you could make a middleware like the following:

    app.use(async (req, res, next) => {
      console.log("Request is going down", req.body)
      await next()
      console.log("Response is coming up", res.data)
      res.send(res.data)
    })

    app.get("/", function (req, res) {
      res.data = { content: "Hello World" }
    })
I don't think anyone was claiming Express and Koa were carbon copies of one another, only that Koa's benefits over Express are minor and Express is much more relevant.

Your claim that "you have to catch your errors or your app can crash" can be addressed trivially. My Express is rusty and I didn't use exact types, but something like this would do:

    type ExpressMiddlewareNextOptional = (req: Record<any, any>, res: Record<any, any>, next?: (error: any) => void) => any;
    type ExpressMiddleware = (req: Record<any, any>, res: Record<any, any>, next: (error: any) => void) => any;

    const mid = (middleware: ExpressMiddlewareNextOptional): ExpressMiddleware => {
      return (req, res, next) => {
        const result = middleware(req, res, next);
        if (result instanceof Promise) {
          result.catch((err) => next(err));
        }
      }
    }
    
    // example usage:
    app.get('somepath', mid(async (req, res) => {
      throw new Error('Oopsie!')
    }))
I used Koa a long time ago before JS had promises and async/await, and it was a relief then, but since Promises the ergonomics of Express have been better (compared to Koa of 8-9 years ago, it's possible Koa is on par or better now). When I started a new project 4 years ago I saw that express had >100X the active usage of Koa, and many, many more packages and pre-built middleware. That's why I say Koa is largely not relevant.

They're both very lightweight libraries, but the ecosystem for Express is much larger, and as mentioned, I've seen maybe 1 company using Koa in the last 5 years. I'm not saying not to use it, and I'm not saying it's not good, but OP was asking for a comparison to "competitors", and I think the ecosystem around a web framework is one of the most important considerations in choosing one. There are thousands of Node.js frameworks, and I'm sure there are many novel ideas among many excellent frameworks I've never even heard of, but the only ones I'd call "competitors" to Express are the ones operating in or near the same weight class. OP mentioned Fastify which is no more than 1 order magnitude away from express in market share, and Koa, which is at least 2 orders of magnitude below Express in active market share. My response was just pointing out that Koa is largely irrelevant when considering Node.js frameworks as "competition to Express".

If they had asked about "alternatives" instead I probably wouldn't have mentioned it "not being a thing", but just pointed out that Express/Koa are spiritually very similar (as two ultra-minimalist frameworks created by TJ Hollowaychuk), but Express's ecosystem is so much larger that someone who isn't already familiar with Koa would very likely be better off choosing Express for anything serious.

Express definitely has a bigger ecosystem and it's what most people, especially beginners, should use.

But they asked how Express 5 compared to competitors, you brought up Koa, someone suggested that Koa was superseded by async/await + some library in Express, and I pointed out Koa's little native feature that still makes it relevant to the few of us who ever used it.

I don't put a lot of importance on microframework ecosystems because 99% of their library middleware is just trivial wrappers around core libraries like https://github.com/jshttp. I write my own glue code in middleware and Koa's abstraction is just what I expect from server code.