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

[Spike] Express vs. Koa for HTTP processing #1255

Closed
hacksparrow opened this issue Apr 13, 2018 · 10 comments
Closed

[Spike] Express vs. Koa for HTTP processing #1255

hacksparrow opened this issue Apr 13, 2018 · 10 comments
Assignees
Labels
Milestone

Comments

@hacksparrow
Copy link
Contributor

hacksparrow commented Apr 13, 2018

Time boxed to 1 week

Created from the discussion at #1071.

Which web framework will we use? find out what is best: express, koa? or do we keep/improve our own homegrown module?
List supported use-cases for http processing; what do we need? CORS, compression, static file serving etc.
Look into maturity, availability of middleware, adoption, etc

This spike is for doing a practical and deeper comparison between Express and Koa for our underlying HTTP framework.

Acceptance Criteria

Should have answers for the following questions (1 question per line).

  • What are the challenges for us LB developers if we use Express / Koa?
  • What are the challenges for our users if the underlying framework is Express / Koa?
  • How does the interface to request and response object change with Express / Koa?
  • How compatible would existing modules be with Express / Koa?
  • Can users switch between Express and Koa as the underlying framework?
  • How does the use of Express / Koa affect routing?
  • How mature / well-supported is Express / Koa?
  • How mature / well-supported are commonly used middleware in Express / Koa?
  • Can we support Express style middleware if we use Koa?
  • Can users customize what will handle HTTP errors - the underlying framework, or LoopBack, or user middleware?
@dhmlau
Copy link
Member

dhmlau commented Apr 20, 2018

@hacksparrow , i've moved this task to In Progress, because you're already working on it.

@hacksparrow
Copy link
Contributor Author

This is currently blocked. We need http-server-koa to be working, before we can do the evaluation.

@raymondfeng
Copy link
Contributor

This is currently blocked. We need http-server-koa to be working, before we can do the evaluation.

It's not necessarily true. We can start to answer most of the questions in this story without having a working http-sever-koa.

@bajtos
Copy link
Member

bajtos commented Apr 26, 2018

I posted few thoughts and review comments for Raymond's RFC pull request, start reading here: #1082 (review)

In the meeting which I watched from the recording, the decision was made to abandon Koa for now and support Express-style middleware only, at least that's my understanding.

I think Koa's design is superior to Express and addresses many pain-points we have encountered during our 5 year jurney with Express, and I really wish we could switch to Koa because I consider it as a more modern successor. However, Express has much larger user base and there are significantly more middleware available. Considering our limited team size and how much work we need to do in other areas, I agree we should NOT pursue Koa and stick to Express for the time being.

To keep our code base simple, I am proposing to assume that LB4 applications (REST servers) will be always mounted as an Express middleware and use request/response types from Express everywhere. Let's not complicate our code by supporting different request/response flavours, when most (if not all) of our users are going to follow our guidance and use LB4 with Express.

The only thing I'd like to keep configurable is the express factory function. I'd like LB4 users to be able to switch from Express to a compatible framework, e.g. https://www.fastify.io or perhaps something based on https://github.com/mafintosh/turbo-http

The specific details about the interaction between Express middleware chain and LB4 sequence, for example error handling, can be discussed and worked out during pull request reviews, at least as far as I am concerned.

@dhmlau
Copy link
Member

dhmlau commented Apr 26, 2018

Just want to add that, from my understanding, if we want to get LB to work with Koa in the future, it is still possible but it involves huge amount of interface porting. @hacksparrow , please correct me if I'm wrong.

On a related note, if someone wants to use Koa instead of Express, can they write an extension to get it to work, or we need to change our own code in order to support both?

@raymondfeng
Copy link
Contributor

@bajtos I think we are on the same page. Here are a few more further clarifications:

  1. [RFC] feat: use express/koa/... as the http framework #1082 already illustrates the possibility to plug in another Http framework by abstracting Request and Response as type aliases and HttpEndpointFactory as the entry point.

  2. We start to leverage some good designs from Koa, for example, using HttpContext to wrap request/response and keep it extensible. We also explore the possibility to allow the cascading middleware style to allow a middleware to await downstream processing.

  3. The most important decision is to settle on Request/Response APIs on Express for now to remove uncertainty.

  4. We plan to spike on a few cases such as adding static and compression to flush out what's the developer UX should be and how to divide responsibility between native Express middleware and our higher level of sequence of actions.

@hacksparrow
Copy link
Contributor Author

@dhmlau the component which interfaces LB4 to a helper HTTP framework is @loopback/rest. To use any custom framework, this component has to be edited.

Reliably porting to Koa from Express might be an effort of 2-3 weeks. The size of this effort depends on various factors - time line, team size etc.

Right now we don't have the provision to write extensions to switch frameworks. But if we want to support in future, some sort of abstraction layer should be added to @loopback/rest.

@bajtos
Copy link
Member

bajtos commented Apr 27, 2018

@raymondfeng your plan sounds good to me!

As for plugging alternate express-compatible implementations like fastify, I'd like us to design our REST layer in such way that express is a dependency that can be left out from projects that are not using it.

For example, if I want to use fastify in my application, then npm install in my app should not fetch express.

I think that means that @loopback/rest must not depend on express directly. Instead, the endpoint factory should receive it as an argument, or perhaps the endpoint factory implementation, which is using express under the hood, should live in it's own package.

I was thinking about the following approach where I assumed the http endpoint factory is a regular function (the code is an illustration only, not something to land as-is):

// in @loopback/rest or similar
export function createHttpEndpoint(app, expressFactory, options) {
  const expressApp = expressFactory();
  expressApp.use(createMiddlewareFromApp(app));
  // setup http server using options
}

// @loopback/rest-express
import * as express from 'express';
export function createHttpEndpoint(app, options) {
  return createHttpEndpoint(app, express, options);
}

Usage in an application - providing my own express version:

import {RestApplication, createHttpEndpoint} from '@loopback/rest';
import * as express from 'express';

const app = new RestApplication();
// configure controllers, etc. perhaps via boot

const server = await createHttpEndpoint(app, express, {port: 3000});

To make this simpler for the majority of users that don't need to/want to know how the sausage is made:

import {RestApplication, createHttpEndpoint} from '@loopback/rest-express';

const app = new RestApplication();
// configure controllers, etc. perhaps via boot

const server = await createHttpEndpoint(app, {port: 3000});

The downside is that rest-express would be tightly coupled with a single version of @loopback/rest and express, people won't be able to choose their own combination of loopback/rest and express versions to mix together.

The upside is that rest-express will allow us to write tests for the particular combination of these two versions and provide our users a combination that's known to work well.

Thoughts?

@dhmlau
Copy link
Member

dhmlau commented May 7, 2018

@hacksparrow , since you have the tasks created from the spike. is this ticket good to close? thanks.

@dhmlau dhmlau closed this as completed May 8, 2018
@shimks shimks added this to the April 2018 milestone May 22, 2018
@bajtos bajtos added the p1 label Aug 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants