Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discussion: Make µExpress a great standalone project, maybe like Koa #2

Open
lbhbrave opened this issue Apr 15, 2018 · 5 comments
Open

Comments

@lbhbrave
Copy link

lbhbrave commented Apr 15, 2018

Original tagline: "this is more like koa in node,why not make it a great project"

@lbhbrave
Copy link
Author

I would to make a koa-like project use swift based swiftnio, after reading your article, this one is what i want to make. its great ,wht not put more effort on that to make it a 'koa' in swift!
I'd like to help if there ant plan!

@helje5
Copy link
Member

helje5 commented Apr 15, 2018

I don't know Koa, well I heard the name before and just re-read the website. To be honest I'm a little confused how exactly this is different to Connect/Express. I see that the API is cleaned up a little.

Could you elaborate a little what you the key points of such a Swift framework would be? I'm certainly open to new ideas!

For now I'm still considering how to couple Noze.io w/ NIO in a neat way. I wrote a little about that in this blog entry.

P.S.: What I definitely do not want to have in a framework is promise-hell (stacks of .then ... .then ... .then - I find that prohibitively ugly). So that may have to wait until Swift 7+. For now my preference here are streams (like this or that).

@helje5 helje5 changed the title this is more like koa in node,why not make it a great project Discussion: Make µExpress a great standalone project, maybe like Koa Apr 15, 2018
@lbhbrave
Copy link
Author

It maybe a little difficult to clarify the difference between express and 'koa'. I'll have a try.
'Express' treats middleWares as a stream, when call next() means current middleWare finishes its work and start next one, like:

req -> step1 -> step2 -> step3 -> res

So if we want to do something when middlewares finish, like logging the duration of (req -res), we need arrange all this code after the last middleware, and we need some ctx object to record previous state like start time :

// use express
app.use(req,  res,  (next) => {
   res.startTime = Date.now();
   next()
});
app.use(req,  res,  (next) => {
   const endTime = Date.now();
   const duration = res.startTime - endTime;
   console.log(duration);
   res.end();
});

Koa treats middleWares as onion-like (from some blogs), when you call next(), it means the rest middleware has finished work.

// use koa
app.use(ctx,  (next) => {
   const startTime = Date.now();
   await next();
   const duration = startTime - Date.now();
   console.log(duration);
});

I ran the µExpress, it operates more like the latter.

This maybe not important. Currently I'm still studying swiftNio as well Noze.io. Also i will give a hand on uExpress if needed.

@helje5
Copy link
Member

helje5 commented Apr 15, 2018

OK, I get that. I was a little confused because you can actually call something after next() in Express too, like:

app.use { req, res, next in
  // do stuff
  next() // this is just a regular callback
  // do more stuff
}

But the Koa setup is more like:

app.use { req, res, next in
  // do stuff
  next()
    .then {
      // do follow up stuff
    }
}

µExpress doesn't actually run like the latter, it runs like Express. That is, if next itself is asynchronous, the stuff below next will run too early.
I guess it would be possible to have µE next return a Future, which you could then hook up to as show above (actually that is a pretty good idea, we should do this). But as mentioned in Koa, this only really makes sense if you have async/await, otherwise it is pretty ugly.

SwiftNIO itself is a little more onion-like where a handler gets triggered on input as well as on output. This is nice for some setups/protocols, but I actually think that the Node streaming model is better. (decoupling input from output, allowing arbitrary piping w/ proper back pressure).

P.S.: Noze.io is not for production use. It is slow due to various reasons (GCD, Swift Generics, etc). But I'd like to have a wrapper on top of NIO which works in a similar way (provides v3 pull streams, type safe streams pipes, and of course have the very-Node/Express like API etc). Still need to think about how to do this well, e.g. whether you would want to enable threading or not (and all the issues which come w/ that).

@helje5
Copy link
Member

helje5 commented Jan 10, 2019

So, actually, because I'm not sure when I get to do the NIO based Noze.io v2, I think it may be worth doing a "MacroExpress".

My thinking is that MicroExpress should really stay Micro and essentially serve the blog article related to it. I don’t want to spam it with too many things.

The idea of MacroExpress would be, that it essentially becomes a thin wrapper around NIO which provides many more Node.js like APIs. Just like Noze.io v2 without the type-safe pull-streams.

By “Macro” I don’t mean that it should become a fat framework. It should essentially work like Noze.io from that perspective: It would have a proper, native (not generated) Xcode project which contains a set of small static libraries one can cherry-pick. While at the same time it could build as an SPM package yielding a set of modules (http, net, etc).
On the Xcode side it could also link those static libs into a single bigger native framework suitable for Carthage, CocoaPods etc.

Macro could be forked of Micro and quickly enhanced with quite a few Noze.io modules. For example Noze.io (like Apex) supports stackable middleware in the respective Express module, which I think is very nice to have. Plus quite a few extra modules already, which would just need to be ported into small Macro modules.

Looks like more people are looking into MicroExpress in search for an easier NIO API, so it may actually make sense to approach that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants