Object isn't an instance of Koa on the "require" side

This is a weird bug so I must be missing something obvious, but here it is.

I'm trying to set up a Koa server to serve several Koa apps depending on the vhost name. The entry point is server.js :

const _ = require("lodash");
const compose = require("koa-compose");
const Koa = require("koa");
const server = module.exports = new Koa();
const app1 = require("./apps/app1");
const app2 = require("./apps/app2");

console.log(app1 instanceof Koa); // false (!)
console.log(app1); // `{ subdomainOffset: 2, proxy: false, env: 'development' }`

const vhostApps = [
  { vhost: "localhost", app: composer(app1) }, // composer fails because app1 is not a Koa instance
  { vhost: "app1.mydomain.com", app: composer(app1) },
  { vhost: "app2.mydomain.com", app: composer(app2) }
];

server.use(async function(ctx, next) {
  const app = _(vhostApps).find({ vhost: ctx.hostname }).app;
  return await app ? app.apply(this, [ctx, next]) : next();
});

if (!module.parent) server.listen(process.env.PORT || 80);

function composer(app) {
  const middleware = app instanceof Koa ? app.middleware : app;
  return compose(middleware);
}

Then, there's ./apps/app1/index.js, the entry point of one app:

const Koa = require("koa");
const serve = require("koa-static");
const views = require("koa-views");
const router = require("./routes");

const app = new Koa();

app.use(serve(__dirname + "/assets"));
app.use(views(__dirname + "/views", { map: { html: "lodash" } }));
app.use(router.routes());

console.log(app instanceof Koa); // true (OK)
console.log(app); // `{ subdomainOffset: 2, proxy: false, env: 'development' }`

module.exports = app;

In this module, app is an instance of Koa (thus it has a middleware property, of type array).

But seen from server.js, the value imported from app1 is not the expected Koa instance, even though the logged values of app and app1 are the same ({ subdomainOffset: 2, proxy: false, env: 'development' } ).

What am I doing wrong?

Upvotes: 3

Views: 176

Answers (1)

Finally I think found what the problem was, and, as it happens, the essential piece of info was missing in my question.

The ./apps/app1 folder has its own node_modules, with its own copy of Koa. Therefore, server.js and apps/app1/index.js each have their own, different, Koa.

So I suppose that in the line: const middleware = app instanceof Koa ? app.middleware : app;, app instanceof Koa will always return false for that reason.

One solution is simply to remove Koa from the app's node_modules, so Koa is inherited from the outer folder. (At first sight, it has some drawbacks for me because I would like to the apps to be standalone).

But I think I'll just skip the instanceof Koa test and have const middleware = app.middleware; instead (I borrowed the original line from https://github.com/koajs/examples/blob/master/vhost/app.js#L14).

Upvotes: 1

Related Questions