Express.js (Node.js): How does static file serving really work?

Problem

I thought serving static files (html, mov, css, jpg, etc.) with Express was going to require some hacks in nginx.

But it seems that static files "just work" with Express. No special thing is required.

  • How does Express static file serving really work?

  • Why do some people advocate using nginx for static files? There must be a good reason for this. (Example: https://gist.github.com/joemccann/644282)

  • Also, while a static file is downloading, does the Node.js event queue get blocked? I suppose not, but why not?

Problem courtesy of: lwood

Solution

If the url does not belong to any paths that you registered via app.get(/... (or POST etc.) methods, Express sends the file if the static path is set and the path that you give belongs to some files path under static files directory. File sending is nothing more than streams, they do not block the event queue completely, they are just pushed to the queue and as chunks recieved, they are piped to the HTTP connection, so they happen on the background of your code. The reason of suggesting nginx is that it is more fit to that job, serving files and routing, and it is also written in C, and optimized for that job, where the NodeJS is a more general-purpose tool compared to Nginx.

Solution courtesy of: Mustafa

Discussion

static file serving is done in express by using the express.static() middleware. This middleware will look on the disk for the files you are presumably asking for, and if found will serve them by writing http headers and then the content. For all of that to work, you will have to app.use(express.static(...)) in your middleware stack.

Using ngnix is advocated due to several reasons, the most important imho are:

  1. It is many times faster

  2. You have more flexibility. With mount point, with rewrite rules, with locations on disk, etc. It's easier to change ngnix configuration than code. Also, this flexibility allows ngnix to handle some or all of the static files, while delegating other work (dynamic content? some other part of the static files) to others (your node.js process, a CDN, etc.)

The node request queue will not be blocked, that's just how node works: requests are handled "quickly", asynchronously, freeing up the single thread to do more work like accepting and handling new requests. Your files are sent "in the background", and you (or really -- the code sending them) are notified when done.

Discussion courtesy of: Nitzan Shaked

In my main server file (app.js) I have.

var express = require('express');
var app = express();
var path = require('path');
...
app.use(express.static(path.join(__dirname, 'public')));

my folders are:

/public/js
/public/css
/public/img

Those are served as static, so no need to restart app to see changes. Can't say about speed vs ngnix, but after reading answer from Nitzan Shaked I'll give ngnix a shot!
EDIT: For this example you'll need connect (npm install connect)

Discussion courtesy of: aesede

This recipe can be found in it's original form on Stack Over Flow.