Let’s say I am writing a web app with a Server and a Client.
- The server functions as an API, and uses express framework.
- The client is just a
node-staticapp that serves static javascript/html files.
I want to be able to deploy them separately, independently of each other – or both at the same time.
Here is how I envision the directory structure:
/my-app
app.js
/server
server.js
/client
client.js
I would like to be able to run this in 3 different ways:
-
Run just the server (API) on some port (say 3000):
my-app/server> node server.js ...Server listening on localhost:3000/api -
Run just the client (i.e. serve static files from /client directory):
my-app/client> node client.js ...Server listening on localhost:4000/client -
Run both the server and the client, on the same port (by single node.js instance):
my-app> node app.js ...Server listening on localhost:5000
Is this possibe in node and what is the proper way to configure it?
I started as follows:
/////////////
// server.js
/////////////
// Run the server if this file is run as script
if(module.parent){
app.listen("3000/client")
}
/////////////
// client.js
/////////////
var static = require('node-static');
var file = new(static.Server)('.');
var app = require('http').createServer(function (request, response) {
request.addListener('end', function () {
file.serve(request, response);
});
});
if(module.parent){
app.listen("4000/client");
}
/////////////
// app.js
/////////////
server = require("server/server.js")
server.app.listen("5000/api")
client = require("client/client.js")
client.app.listen("5000/client") <--- ?????
I am not sure how to hook up both client and server inside my app.js so that they are both served from the same port/process/thread etc…
NOTE: Excuse the code, it is not tested and probably incorrect. I am new to node.js
Any tips appreciated.
You can instantiate a
connect(the guts ofexpress) server instance when starting both the server and the client from the same script and have it route the requests tonode-staticwhen the url starts withpublicand toconnectotherwise.Something like
should do. You’ll need to expose the
function(request, response)inclient.jsso that it can be referenced throughclient.handler_functionand do the same for the express app (refer to the documentation).For example, esposing the function in
client.jswould involve something like:So that you can get to
handlerby doing:Other approaches
What I’ve detailed above seems to be the closest to what you want (based on the clarification in your last edit). There are other options, though:
keep static and express-generated urls based at the site root, such as
example.com/a_statically_served_script.jsandexample.com/api_endpoint; serving a static file is attempted first, if one cannot be found you’ll dispatch the request to the express-based appuse the
app.jsscript to start both servers on different ports (or unix domain sockets) and use node-proxy (or something similar, or even nginx/apache as a reverse proxy) in front of themSame root
For the first approach you need to add an error handler to
file.servesuch asnextshould be a variable in theclient.jsscript that is not set when the script is run directly but it is when the script is required (have a look at the documentation for how modules and exports in node work) – when set,nextrefers to a function that takes(req, res)and feeds them to express (have a look at the express docs on how to do this).Remarks
Keep in mind this isn’t an exhaustive answer: it’s just a bunch of pointers on what documentation to look up and what techniques you could use to solve the problems.
Something worth remembering is that more often than not in node a request handler is represented and implemented by a
function(request, response). This idiom is extended inconnect/expresstofunciton(request, response, next): herenextrepresents the next avaliable handler (of the formfunction(request, response)) in the chain of handlers mounted to the server throughserver.use(handler).