Serving Static Files using Express in Node JS

 

Static files form a main component of the world wide web we know. Every site has atleast one html page. To serve these files to the customer you can either use servers like APACHE or any server of your choice. Here we will see how to send file from NodeJS. We can send files through an http server but this article will demonstrate the use of ExpressJS as you would be using more of it. 

First of all setup a project structure as shown below:



The index.html file inside the public directory contain some html code. You can write whatever html code you want. Lazy?? Just copy paste this page’s source code. 

Since we will be using ExpressJS, make it a habit to install the following modules when creating a project:
  • express
  • body-parser
  • cookie-parser
Cookie-parser is used to parse request cookies into the object req.cookies. Just remember this, we’ll use it later.

Naive Approach
In the server.js file, write the following:

server.js

"use strict";
const express = require('express');
const path = require('path');

var app = express();
let PORT = 3000;

var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

app.get('/', function(req, res){
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

app.listen( PORT, function(){
    console.log("Server started listening on port: "+PORT);
});

In the / route handler, we use the res.sendFile method to send the file to the client. This method requires an absolute path which is why use the path module.

Start the server and visit localhost:3000 in your web browser. You should see something like this:

But wait. No styling has been done even though we included a css file. Check the developer console of your browser.


It says that index.css not found. But it was there in the folder right?

The problem is that whenever the html requests any CSS or JS file, it is actually sending another GET request to the server at the route http://<domain name>/index.css. Now since we don’t have any handler set for /index.css route. To solve this add the following in the server.js file:


app.get('/index.css', function(req, res){
  res.set('Content-Type', 'text/css');
  res.sendFile(path.join(__dirname, 'public', 'index.css'));
});

Here we create a handler for /index.css route which sends the css file. We would also need to specify the Content-Type header so that the file is interpreted correctly.
Now run the server and check the site:


Here we create two new endpoints, one for index.css and one for index.js. When a request is made to these endpoints, the server reads the required files and sends them with the correct content-type header.

Now restart the server and go to “http://localhost:3000” . Now this works fine.

This is a tedious task. Suppose there are hundreds of static files, then for each you would need to write an endpoint. This becomes very time consuming and boring task to do. It is also a waste of developer time. To solve this problem, the developers of ExpressJS introduced a support for serving static files directly from the express without having to write endpoints for each of the file. We just need to write the endpoints for those URLs which we need to customise. All the dependent URLs like for CSS, JS, Images, Audio, Video etc etc will be handled by ExpressJS. 

Pretty cool…!!! Let’s see how to do this.

Adding Express Static Magic

This is a simple thing to do. Modify the server.js file as below i.e remove all the CSS and JS endpoints and tell the existing app to use the express.static() function.


"use strict";

const express = require('express');
const path = require('path');

var app = express();
let PORT = 3000;

var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

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

app.get('/', function(req, res){
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

app.listen( PORT, function(){
    console.log("Server started listening on port: "+PORT);
});

Observe that we removed all the unnecessary endpoints from our app. Instead we tell the app to use the static feature of ExpressJS. This function accepts one argument -- the folder in which the app should search for static files. Here since all the static files are stored in the public folder, we specify the path to public directory as an argument to the static function.

Now whenever a request is made to the our server, it first check if the URL matches any file in the public directory. If it finds a file then the file is sent with the correct headers. If it is not, the the app looks for other handlers to handle the URL. If no handler is specified, the server will return a 404 - Not found status to the client.

We have kept the GET / endpoint in our code as we wanted to send the html page with a request is made to the / URL. If we remove the handler for this URL, then you need to go to “http://localhost:3000/index.html” to see your HTML page.

The express.static() function is a middleware exposed by the express module. We will see more about middlewares in the later tutorials.

Is it necessary to put the files in public folder only?
No. You can name the folder whatever you want. You need to specify the argument to the express.static() accordingly. It is recommended to put all the static files in a single folder. If you put the static files in the root folder, then the script may behave weirdly sometimes.

This is how you can easily serve static files to the clients using ExpressJS.


No comments:
Write comments

Popular Posts