Let's learn how to use javascript to program a server based on Node.js and upload the website to Heroku. First, a simple server; write this in a file called app.js:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
Then in a file called .gitignore we will write this:
node_modules
Lastly, let's install express, our server framework.
npm install express --save
We will also install nodemon since it makes things much easier:
npm install nodemon -g
Now we can see that message on the server. Run nodemon and open localhost:3000:
nodemon
Routing
Now let's tell our server what files and how it should display. First let's just display index.html. In app.js, write this instead of our previous 'Hello world':
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
If we reopen localhost:3000 and refresh it we can see our index.html without any style or javascript.
Then we also want our server to know where our css and (front-end) javascript is, so we will add this and put those files in there:
app.use(express.static('public'));
Now let's catch the files dynamically (routing). We will get the url fragment as the variable path and then use it:
app.get('/:name', function (req, res) {
console.log(req.params);
res.send(req.params);
});
The previous one only shows us in the terminal what file we are reading, now let's actually show it:
app.get('/:name', function (req, res) {
var file = __dirname + '/' + req.params.name + '.html';
res.sendFile(file);
});
Forms
Let's try to create a form and handle it with Node.js. First we create the form in contact.html:
<!DOCTYPE html>
<html>
<head>
<title>Página Web</title>
<meta charset="utf-8">
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/picnicss/6.1.1/picnic.min.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<form action="/contacto" method="POST" class="contact">
<h1>Contacto</h1>
<input placeholder="Nombre">
<input placeholder="Apellidos">
<input placeholder="Edad">
<input type="submit" value="Enviar">
</form>
</body>
</html
And in style.css:
.contact {
width: 500px;
margin: 100px auto;
}
.contact input {
margin-top: 0;
margin-bottom: 10px;
}
Then we install body-parser, it's a library to read easier the forms from the back-end:
npm install body-parser --save
After that, in app.js we setup the library:
var bodyparser = require('body-parser');
// ...
app.use(bodyparser.urlencoded({ extended: false }));
Now we can use it to read the data. So far we won't be storing it, just display it on the terminal:
app.post('/contact', function(req, res){
console.log(req.body);
res.redirect('/');
});
If everything worked fine, this should accept our data from the contact form and then redirect us home. We could change this for a /thankyou.html page or just handle it with javascript on the front-end and not redirect anywhere.
REST API
A REST API is one group of url and action that can be done to them. For instance, let's say we have a user system. This would be a basic REST API:
GET /users # Get all of the users data
GET /users/456546 # Get one specific user data
POST /users # Create a new user
PUT /users/435465 # Edit an existing user
DELETE /users # Remove all the users
DELETE /users/354643 # Remove a single user
This is useful for example with React.js, Angular, etc. It separates our logic at some specific points and makes it easier to handle the complexity.
Let's make a small API that handles a Like button. In our app.js:
// An array with the ids of the things we liked
var likes = [];
// Retrieve all of our likes
app.get('/likes', function(){
res.json({
likes: likes
});
});
// Create a new like
app.post('/likes/:id', function(req, res){
var id = req.params.id;
likes.push(req.params.id);
res.json({ added: true });
});
app.delete('/likes/:id', function(req, res){
var id = req.params.id;
var index = likes.indexOf(id);
likes.splice(index, 1)
res.json({ deleted: true });
});
Now we can have a list of items that can be liked:
<main> <ul> <li>First <button data-id="1">Like</button></li> <li>Second <button data-id="2">Like</button></li> <li>Third <button data-id="3">Like</button></li> <li>Fourth <button data-id="4">Like</button></li> </ul> </main> <script> // Load all the likes and add the class 'active' to the ones we liked $(document).ready(function(){ $.get('/likes/', function(res){ res.likes.forEach(function(id){ $('button[data-id="' + id + '"]').addClass('active'); }); }); }); // Handle the button clicks $('button').on('click', function(e){ var id = $(e.target).attr('
data-id'); var isLiked = $(e.target).hasClass('active'); $.ajax(url, { url: '/likes/' + id, method: isLiked ? 'DELETE' : 'POST', success: function(){ $(e.target).toggleClass('active'); console.log('Good job!'); }
}); }); </script>
Exercise: make a dislike button that calls the route /dislike through POST and DELETE and shows on the browser console what the server is doing.