Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A Sapper-compatible setup to serve multiple apps from a single Express/Polka entry point

I need to set up a Polka (or Express) server so that it can serve multiple applications (one per hostname) from a single server.js entry point. It can be done using the vhost middleware (https://github.com/expressjs/vhost). Each app is exported as a middleware, and the one that corresponds to each request is added in the middleware chain in server.js.

However, some (not all) of these apps will be Sapper applications so the setup must be compatible with Sapper. So far as I am aware, Sapper builds generate a server.js file which works as entry point for the app, but the app is not exported. Is there a build option to export the Sapper app (instead of doing listen on it)? Or some other way to do this?

I've tried to manually edit a build and it seems to work, although there are some issues with file paths because the root of the Sapper app is not that of the main application.

I've looked up this problem but didn't find any reference to it, so I am wondering if I am taking a wrong path and if there is a more obvious solution. (Note: the Node.js hosting I am using doesn't allow to map hostnames to app folders, which would of course make things simpler.)

like image 472
Nicolas Le Thierry d'Ennequin Avatar asked Dec 09 '20 10:12

Nicolas Le Thierry d'Ennequin


1 Answers

Solution #1: Export Sapper app as a middleware

You can make your own export of Sapper app. In server.ts/server.js of your Sapper app, instead of starting the server you can export a middleware. Something like this:

import * as sapper from "@sapper/server";
export const handler = sapper.middleware();

Then in your express app just map the domain to exported middleware:

const express = require('express');
const vhost = require('vhost');
const path = require('path');
const { handler } = require('./__sapper__/build/server/server');


const app = express();

app.use(vhost('*.example.com', (req, res, next) => {

  if (req.vhost[0] === 'sapper') {
    return handler(req, res, next);
  }

  return res.statusCode(400);
}))

app.listen(3000, () => console.log('Server started'));

Solution #2: Use a reverse proxy

Another solution would be to run all the nested applications in different ports on the server and use a revers proxy to route the requests accordingly.

For running the nested applications on different ports, possible solution would be dockerizing them or using the pm2.

For the reverse proxy part you could use Nginx or Traefik. Also it is possible to write a reverse proxy middleware to handle it programmatically using http-proxy-middleware

like image 163
Ham3d Avatar answered Nov 04 '22 12:11

Ham3d