Showing posts with label Express. Show all posts
Showing posts with label Express. Show all posts

Thursday, 11 July 2013

Creating a basic site with node.js and Express

walkthrough on how to create and deploy a basic site with node.js and the Express framework

What we are going to do

This walkthrough will go over setting up a basic site using node.js and Express. The walkthrough is aimed at beginners exploring node.js as I've had many questions from friends and colleagues about creating and deploying node apps. If you are not a beginner the article probably won't be of much use to you. We are going to use express, an excellent web framework for node created by TJ Holowaychuk who seems to be pumping out node.js libraries like he was ten men.
Here is the site we are going to create. You might also want to grab the source code.
Example Express website

Setup

First we need to setup our development environment. If you are on OSX I'vecovered how to setup node.js and npm on OSX in a previous article. If you haven't got everything installed follow that article.
If you are on Linux there are plenty of articles on Google.
For Windows users there are also resources on Google but it is a bit more tricky.

Prerequisites

If everything has installed ok you should now have node.js and npm running on your machine. At the terminal type node -v and npm -v and you should see something like:
node -v
v0.8.21
npm -v
1.2.12

Create an Express site

Still with me? We've covered a lot already! Now let's create an Express site.
First let's install express
npm install -g express
The -g flag means that you are installing express globally on your system.
Now we can create an express application.
express -c stylus express_example
The -c states that we want to use stylus for css. You should see the following output:
create : express_example
create : express_example/package.json
create : express_example/app.js
create : express_example/public
create : express_example/public/javascripts
create : express_example/public/images
create : express_example/public/stylesheets
create : express_example/public/stylesheets/style.styl
create : express_example/routes
create : express_example/routes/index.js
create : express_example/routes/user.js
create : express_example/views
create : express_example/views/layout.jade
create : express_example/views/index.jade

install dependencies:
 $ cd express_example && npm install

run the app:
 $ node app
As per the instructions you'll need to install dependencies so do this
cd express_example && npm install
This will install packages and you will see a lot of output. When this is complete you can boot your application.

Boot the app

That's all the setup you need. Phew. Now you can boot the app:
node app.js
You should see Express server listening on port 3000 and if you open http://127.0.0.1:3000 you'll see the default Express page.

Using Git

Git is a version control system that is used heavily in the node.js ecosystem, particulary with Github. If you aren't familiar with Git Scott Chacon is your go-to man. He's written extensively and eloquently on Git for beginners and experts. Checkout Gitcasts for if you are a beginner and ProGit for more advanced stuff. We are going to use git to version our site and publish it so let's set up our repo now. If your Express server is still running hit CTRL + C to stop it.
git init
git add .
git commit -m 'initial commit'

Developing node.js sites

Normally when you develop a node.js site you'll need ot restart your application each time you make a change. Thankfully our home-grown British JavaScript genius Remy Sharp has solved this problem with nodemon. Nodemon will reload your application each time it changes so you don't need to restart it. If you have used Shotgun for Ruby with Sinatra it is similar to that. To install run
npm install -g nodemon
Then you can start your app with
nodemon app.js
Using nodemon means you don't have to restart your app each time you make a change. For more infomation on nodemon see the README

HTML in Express

Express is agnostic as to which templating language you use. Templating languages can be a hot topic of debate but for this article I'm going to use jade. If you've used haml it is similar to that. In the example we use jade to setup a layout template.
!!! 5
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
    link(rel='stylesheet', href='/stylesheets/chunkfive-fontface.css')
  body
    header
      nav
        ul
          li 
            a(href="/") Home
          li 
            a(href="/about") About
          li 
            a(href="/contact") Contact
    section#wrapper!= body
        footer 
          section.css-table
            section.four-column
              section.cell
                p Mauris porttitor <br />felis eu leo aliquet<br /> ac rutrum odio aliquet
              section.cell
                p Mauris porttitor <br />felis eu leo aliquet<br /> ac rutrum odio aliquet
              section.cell
                p Mauris porttitor <br />felis eu leo aliquet<br /> ac rutrum odio aliquet
              section.cell
                p Mauris porttitor <br />felis eu leo aliquet<br /> ac rutrum odio aliquet
This is a common template we can reuse. The line section#wrapper!= body pulls in content from the page it is used on. Express also supports variables that you pass through to the template. In this case we pass the title variable. If you are coming from Sinatra this will all be familiar to you. If you are not I recommend consulting the Express documentation.

CSS in Express

Again Express is agnostic to what you use to generate your CSS - you can use vanilla CSS but for this example I'm using Stylus. This is very similar to Sassand supports variables, mixins, functions and more. I really like it! Here's an example from our stylesheet
body
  font 62.5%/1.5  Helvetica, Arial, "Lucida Grande", "Lucida Sans", Tahoma, Verdana, sans-serif
  text-align center
  background #000

#wrapper
  width 920px
  text-align left 
  margin-left auto 
  margin-right auto
  background #fff
  padding 20px
  border-bottom-radius(15px)
You'll see that stylus is very terse - you don't need brackets or commas.

Routing in Express

Routing is similar to Sinatra, allowing you to set up RESTful routes.
In this example we setup three routes in app.js
app.get('/', function(req, res){
  res.render('index', {
    title: 'Home'
  });
});

app.get('/about', function(req, res){
  res.render('about', {
    title: 'About'
  });
});

app.get('/contact', function(req, res){
  res.render('contact', {
    title: 'Contact'
  });
});
See the Express documentation for more.

Publishing your site

We've now developed a basic node.js site using express and we want to host it somewhere. Publishing the site to Heroku is free and you can be up and running in no time. You can sign up for an account at Heroku for free and then install the toolbelt.
To make your example node site work with Heroku you must create a file called Procfile in the root of the project. Add the following.
web: node app.js
To make sure Heroku uses the correct versions of node add this to the package.json file
"engines": {
  "node": "0.8.x",
  "npm": "1.2.x"
}
Then you can use the command line tools to create a site on Heroku and publish it.
heroku apps:create 
git push heroku master
Easy!
Some other node.js hosting providers include nodejitsuJoyentCloud Foundry and Duostack.

Conclusion

This article has showed how to create a very basic site using node.js and Express. It has introduced a number of things from the node.js ecosystem and showed you how to deploy your app to Nodester.
The strengths of node.js as a technology are not so much in building static websites like this. I encourage you to explore some of the node.js libraries to see what it can do. Particularly for real-time applications node.js is extremely exciting and I think we'll see some great apps built on node.js. Try starting with socket.io for a taste of what to expect.

Real Time Chat With NodeJS, Socket.io and ExpressJS

NodeJS gives me the ability to write back-end code in one of my favorite languages: JavaScript. It's the perfect technology for building real time applications. In this tutorial, I'll show you how to build a web chat application, using ExpressJS and Socket.io.

Setup Environment

Of course, the first thing to do is get NodeJS installed on your system. If you are a Windows or Mac user, you can visit nodejs.org and download the installer. If you instead prefer Linux, I'd suggest that you refer to this link. Although I won’t go into further details on this, if you encounter any installation issues, I’m happy to help; just leave a comment below this post.
Once you have NodeJS installed, you’re ready to setup the needed instruments.
  1. ExpressJS – this will manage the server and the response to the user
  2. Jade – template engine
  3. Socket.io – allows for real time communication between the front-end and back-end
Continuing on, within an empty directory, create a package.json file with the following content.
1
2
3
4
5
6
7
8
9
10
11
{
    "name": "RealTimeWebChat",
    "version": "0.0.0",
    "description": "Real time web chat",
    "dependencies": {
        "socket.io": "latest",
        "express": "latest",
        "jade": "latest"
    },
    "author": "developer"
}
By using the console (under Windows – command prompt), navigate to your folder and execute:
1
npm install
Within a few seconds, you’ll have all the necessary dependencies downloaded to the node_modulesdirectory.

Developing the Backend

Let’s begin with a simple server, which will deliver the application's HTML page, and then continue with the more interesting bits: the real time communication. Create an index.js file with the following core expressjscode:
1
2
3
4
5
6
7
8
9
10
var express = require("express");
var app = express();
var port = 3700;
app.get("/", function(req, res){
    res.send("It works!");
});
app.listen(port);
console.log("Listening on port " + port);
Above, we’ve created an application and defined its port. Next, we registered a route, which, in this case, is a simple GET request without any parameters. For now, the route’s handler simply sends some text to the client. Finally, of course, at the bottom, we run the server. To initialize the application, from the console, execute:
1
node index.js
The server is running, so you should be able to open http://127.0.0.1:3700/ and see:
1
It works!
Now, instead of "It works" we should serve HTML. Instead of pure HTML, it can be beneficial to use a template engine. Jade is an excellent choice, which has good integration with ExpressJS. This is what I typically use in my own projects. Create a directory, called tpl, and put the following page.jade file within it:
1
2
3
4
5
6
7
8
9
!!!
html
    head
        title= "Real time web chat"
    body
        #content(style='width: 500px; height: 300px; margin: 0 0 20px 0; border: solid 1px #999; overflow-y: scroll;')
        .controls
            input.field(style='width:350px;')
            input.send(type='button', value='send')
The Jade's syntax is not so complex, but, for a full guide, I suggest that you refer to jade-lang.com. In order to use Jade with ExpressJS, we require the following settings.
1
2
3
4
5
6
app.set('views', __dirname + '/tpl');
app.set('view engine', "jade");
app.engine('jade', require('jade').__express);
app.get("/", function(req, res){
    res.render("page");
});
This code informs Express where your template files are, and which template engine to use. It all specifies the function that will process the template's code. Once everything is setup, we can use the .rendermethod of the response object, and simply send our Jade code to the user.
The output isn’t special at this point; nothing more than a div element (the one with id content), which will be used as a holder for the chat messages and two controls (input field and button), which we will use to send the message.
Because we will use an external JavaScript file that will hold the front-end logic, we need to inform ExpressJS where to look for such resources. Create an empty directory, public, and add the following line before the call to the .listen method.
1
app.use(express.static(__dirname + '/public'));
So far so good; we have a server that successfully responds to GET requests. Now, it’s time to addSocket.io integration. Change this line:
1
app.listen(port);
to:
1
var io = require('socket.io').listen(app.listen(port));
Above, we passed the ExpressJS server to Socket.io. In effect, our real time communication will still happen on the same port.
Moving forward, we need to write the code that will receive a message from the client, and send it to all the others. Every Socket.io application begins with a connection handler. We should have one:
1
2
3
4
5
6
io.sockets.on('connection', function (socket) {
    socket.emit('message', { message: 'welcome to the chat' });
    socket.on('send', function (data) {
        io.sockets.emit('message', data);
    });
});
The object, socket, which is passed to your handler, is actually the socket of the client. Think about it as a junction between your server and the user's browser. Upon a successful connection, we send a welcometype of message, and, of course, bind another handler that will be used as a receiver. As a result, the client should emit a message with the name, send, which we will catch. Following that, we simply forward the data sent by the user to all other sockets with io.sockets.emit.
With the code above, our back-end is ready to receive and send messages to the clients. Let's add some front-end code.

Developing the Front-end

Create chat.js, and place it within the public directory of your application. Paste the following code:

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
window.onload = function() {
    var messages = [];
    var socket = io.connect('http://localhost:3700');
    var field = document.getElementById("field");
    var sendButton = document.getElementById("send");
    var content = document.getElementById("content");
    socket.on('message', function (data) {
        if(data.message) {
            messages.push(data.message);
            var html = '';
            for(var i=0; i<messages.length; i++) {
                html += messages[i] + '<br />';
            }
            content.innerHTML = html;
        } else {
            console.log("There is a problem:", data);
        }
    });
    sendButton.onclick = function() {
        var text = field.value;
        socket.emit('send', { message: text });
    };
}
Our logic is wrapped in a .onload handler just to ensure that all the markup and external JavaScript is fully loaded. In the next few lines, we create an array, which will store all the messages, a socket object, and few shortcuts to our DOM elements. Again, similar to the back-end, we bind a function, which will react to the socket's activity. In our case, this is an event, named message. When such an event occurs, we expect to receive an object, data, with the property, message. Add that message to our storage and update thecontent div. We’ve also included the logic for sending the message. It’s quite simple, simply emitting a message with the name, send.
If you open http://localhost:3700, you will encounter some errors popup. That's because we need to updatepage.jade to contain the necessary JavaScript files.
1
2
3
4
head
    title= "Real time web chat"
    script(src='/chat.js')
    script(src='/socket.io/socket.io.js')
Notice that Socket.io manages the delivery of socket.io.js. You don't have to worry about manually downloading this file.
We can again run our server with node index.js in the console and open http://localhost:3700. You should see the welcome message. Of course, if you send something, it should be shown in the content'sdiv. If you want to be sure that it works, open a new tab (or, better, a new browser) and load the application. The great thing about Socket.io is that it works even if you stop the NodeJS server. The front-end will continue to work. Once the server is booted up again, your chat will be fine too.
In its current state, our chat is not perfect, and requires some improvements.

Improvements

The first change that we need to make is to the identity of the messages. Currently, it's not clear which messages is sent by whom. The good thing is that we don't have to update our NodeJS code to achieve this. That's because the server simply forwards the data object. So, we need to add a new property there, and read it later. Before making corrections to chat.js, let’s add a new input field, where the user may add his/her name. Within page.jade, change the controls div:
1
2
3
4
5
6
.controls
    | Name:
    input#name(style='width:350px;')
    br
    input#field(style='width:350px;')
    input#send(type='button', value='send')
Next, in code.js:
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
28
29
30
31
32
33
window.onload = function() {
    var messages = [];
    var socket = io.connect('http://localhost:3700');
    var field = document.getElementById("field");
    var sendButton = document.getElementById("send");
    var content = document.getElementById("content");
    var name = document.getElementById("name");
    socket.on('message', function (data) {
        if(data.message) {
            messages.push(data);
            var html = '';
            for(var i=0; i<messages.length; i++) {
                html += '<b>' + (messages[i].username ? messages[i].username : 'Server') + ': </b>';
                html += messages[i].message + '<br />';
            }
            content.innerHTML = html;
        } else {
            console.log("There is a problem:", data);
        }
    });
    sendButton.onclick = function() {
        if(name.value == "") {
            alert("Please type your name!");
        } else {
            var text = field.value;
            socket.emit('send', { message: text, username: name.value });
        }
    };
}
To summarize the changes, we’ve:
  1. Added a new shortcut for the username's input field
  2. Updated the presentation of the messages a bit
  3. Appended a new username property to the object, which is sent to the server
If the the number of messages becomes too high, the user will need to scroll the div:
1
2
content.innerHTML = html;
content.scrollTop = content.scrollHeight;
Keep in mind that the above solution will likely not work in IE7 and below, but that’s okay: it’s time for IE7 to fade away. However, if you want to ensure support, feel free to use jQuery:
1
$("#content").scrollTop($("#content")[0].scrollHeight);
It would also be nice if the input field is cleared after sending the message:
1
2
socket.emit('send', { message: text, username: name.value });
field.value = "";
The final boring problem is the clicking of the send button each time. With a touch of jQuery, we can listen for when the user presses the Enter key.
1
2
3
4
5
6
7
$(document).ready(function() {
    $("#field").keyup(function(e) {
        if(e.keyCode == 13) {
            sendMessage();
        }
    });
});
The function, sendMessage, could be registered, like so:
1
2
3
sendButton.onclick = sendMessage = function() {
    ...
};
Please note that this isn’t a best practice, as it is registered as a global function. But, for our little test here, it’ll be fine.

Conclusion

NodeJS is an extremely useful technology, and provides us with a great deal of power and joy, especially when considering the fact that we can write pure JavaScript. As you can see, with only a few lines of code, we managed to write a fully functional real time chat application. Pretty neat!