This is an outdated post about how I structure multiple node.js website hosted on one machine.

I bought my domain gisonrg.me in year 2013, when I got plenty of time, and wanted to learn as much as I can as a year one student. Then the site was abandoned because I was busy with my course studies (or because I was lazy?). Then one day, I picked it up again for some months, and once again abandoned till now. As I realized that I actually do have something to share throughout my developing experience.

I used to host the website on Apache because that’s the starting point of my web development - PHP, MySQL and Apache. Later on, as the raise of Node.js, I removed the Apache stack totally, and switch to develop this newly emerging technology.

The homepage of gisonrg.me, is just a single-paged website developed with Express framework. I chose to use the framework instead of a single html page because I believed I may extend the website for other purposes. I was right, as during this summer when I was developing a Bus timing application, I need to create a daemon to constantly pull data from the server and cache them in a Redis server, and designed the API so user could get data from it. This is why RESTful framework are so easy to use. I simply created a new router in my existing application:

1
2
3
4
5
6
7
8
9
// In app.js
// use a new middleware when url matches /api
var api = require('./routes/api');
app.use('/api', api);

// In api.js
router.get('/bus/', function(req, res) {
// return bus time for all station
});

And then just visit gisonrg.me/api/xxx, I can add whatever api here without affecting my old website. How cool is that.

Later, I decide to add a blog to my website as well. And I plan to host it under a subdomain - blog.gisonrg.me.
In apache, it is very tedious to enable subdomain, as you need to configure the server carefully and make sure everything works. While using Node.js with Express, it is quite easy to add a virtual host to support your subdomain.

You need two Node.js application running at the same time, and let another app as an entrance to redirect the request to the designated app.
But first of all, you need to add one CNAME record so that the subdomain will point to your domain correctly. I am using digital ocean, so here is my setting:

Also you can change the ‘wildcard ‘ to ‘blog’, but since I only have a single IP, I will use to ease everything.

Next, we can use Express’s virtual domain hosting middleware ‘vhost’ to enable our subdomain. Install the component.

1
$ npm install vhost

Next, since we need an centralized entrance, so I created a bootstrap.js:

1
2
3
4
5
6
7
8
9
10
11
12
var express = require('express');
var vhost = require('vhost');
var app = module.exports = express();

app.use(vhost('gisonrg.me', require('./app.js')));
app.use(vhost('blog.gisonrg.me', require('./blog.js')));

app.set('port', process.env.PORT || 3000);

var server = app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + server.address().port);
});

So we have two Express application, one is in app.js, another is in blog.js. And we could start the web app by

1
node bootstrap.js

And we are done :) We have two application up and running with one at gisonrg.me and one at blog.gisonrg.me.

However, at first, I thought I can develop my own blog from scratch. It is not hard, but then I was not satisfied with what I have developed. Then I found it would be just better if I use an existing blog framework so I can focus on blogging. And I found it - Hexo. It supports markdown, gives me enough flexibility, and plenty of themes and plugins.

However, when the blog is settled down, another problem occurred. Hexo is a stand-alone application. The vhost can no longer be used as Hexo cannot be required as an Express application. So you cannot do things like

1
app.use(vhost('blog.localhost', require('./hexoBlog.js')));

anymore.

The solution is quite simple actually, just use pure HTTP proxy will do.
Whenever a request for the subdomain that relates to blog is received, proxy all request to your hexo application. All you need to do is using a package called ‘http-proxy’.

Here is the updated bootstrap.js file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var express = require('express');
var vhost = require('vhost');
var httpProxy = require('http-proxy');

var app = module.exports = express();


var proxy = httpProxy.createProxyServer({});

app.use(function (req, res, next) {
if (req.headers.host) {
if (typeof req.headers.host === 'string' && req.headers.host.match(/blog\.gisonrg\.me/)) { // a simple url match.
proxy.web(req, res, { target: 'http://0.0.0.0:4000/' }); // hexo is running on this host and you can change it.
} else {
next(); // pass the request to other app.
}
}
});

app.use(vhost("gisonrg.me", require('./app.js')));
app.use(vhost('*.gisonrg.me', require('./app.js')));

app.set('port', process.env.PORT || 3000);

var server = app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + server.address().port);
});

I still make use of vhost so I could redirect all non-existing subdomain request to the main application :D.