In this tutorial we’ll explore the Express NodeJS framework. It provides all of the capabilities of NodeJS, also makes it easy to build robust web applications quite easily using a MVC format. I’ll cover how to install on Windows, Mac and Linux. We’ll then explore building the server, routes, incorporating Handlebars, incorporating Bootstrap, ports, middleware, app.use, app.get, catching / throwing errors, handling forms, file uploads, cookies, sessions, reading / writing files and much more.
This will serve as an overview of the whole Express framework, while the next tutorial will how to incorporate a MongoDB database into an Express app. All of the code is down below.
If you like videos like this, it helps me if you tell Google with a click here [googleplusone]
The code and images are here for download
Code From the Video
expresstut.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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
// We will structure here a series of possible responses // depending on the URL requested. As we travel through // the pipeline we will perform needed actions using middleware // functions. If a response is valid we will display the // correct view and if not we will handle errors. // This is our projects entry point. If you start the // server by typing node expresstut.js and then open the // browser at loclhost:3000 you'll get a 404 error if // you haven't defined any routes // Import the express module var express = require('express'); var app = express(); // Block the header from containing information // about the server app.disable('x-powered-by'); // Set up Handlebars // Create a directory named views and then another named layouts // in it // Define main.handlebars as the default layout // Create these files in the views directory and define the // HTML in them home.handlebars, about.handlebars, // 404.handlebars and 500.handlebars var handlebars = require('express-handlebars').create({defaultLayout:'main'}); app.engine('handlebars', handlebars.engine); app.set('view engine', 'handlebars'); // Required when using POST to parse encoded data // npm install --save body-parser app.use(require('body-parser').urlencoded({extended: true})); // Formidable is required to accept file uploads // npm install --save formidable var formidable = require('formidable'); // Import credentials which are used for secure cookies // Install the cookie middleware // npm install --save cookie-parser var credentials = require('./credentials.js'); app.use(require('cookie-parser')(credentials.cookieSecret)); // Defines the port to run on app.set('port', process.env.PORT || 3000); // Create a directory called public and then a directory // named img inside of it and put your logo in there app.use(express.static(__dirname + '/public')); // Define some routes. app.get receives a path and a // function and it defines our routes. The path isn't // case sensitive and doesn't care about trailing path // information. // The req object represents the HTTP request and // contains the query string, parameters, body, header // The res object is the response Express sends // when it receives a request app.get('/', function(req, res){ // Point at the home.handlebars view res.render('home'); }); // This is an example of middleware It receives a request // object, response object and the next function // As we look for the correct information to serve it executes // and then next() says to continue down the pipeline app.use(function(req, res, next){ console.log('Looking for URL : ' + req.url); next(); }); // You can also report and throw errors app.get('/junk', function(req, res, next){ console.log('Tried to access /junk'); throw new Error('/junk does\'t exist'); }); // Catches the error and logs it and then continues // down the pipeline app.use(function(err, req, res, next){ console.log('Error : ' + err.message); next(); }); // If we want /about/contact we'd have to define it // before this route app.get('/about', function(req, res){ // Point at the about.handlebars view // Allow for the test specified in tests-about.js res.render('about'); }); // Link to contact view app.get('/contact', function(req, res){ // CSRF tokens are generated in cookie and form data and // then they are verified when the user posts res.render('contact', { csrf: 'CSRF token here' }); }); // Sent here after the form is processed app.get('/thankyou', function(req, res){ res.render('thankyou'); }); // Receive the contact form data and then redirect to // thankyou.handlebars // contact.handlebars calls process to process the form app.post('/process', function(req, res){ console.log('Form : ' + req.query.form); console.log('CSRF token : ' + req.body._csrf); console.log('Email : ' + req.body.email); console.log('Question : ' + req.body.ques); res.redirect(303, '/thankyou'); }); // Open file-upload.handlebars and store the current year // and month. When the form is submitted the year and month // will be passed app.get('/file-upload', function(req, res){ var now = new Date(); res.render('file-upload',{ year: now.getFullYear(), month: now.getMonth() }); }); // file-upload.handlebars contains the form that calls here app.post('/file-upload/:year/:month', function(req, res){ // Parse a file that was uploaded var form = new formidable.IncomingForm(); form.parse(req, function(err, fields, file){ if(err) return res.redirect(303, '/error'); console.log('Received File'); // Output file information console.log(file); res.redirect( 303, '/thankyou'); }); }); // Demonstrate how to set a cookie app.get('/cookie', function(req, res){ // Set the key and value as well as expiration res.cookie('username', 'DerekBanas', {expire : new Date() + 9999}).send('username has the value of : DerekBanas'); }); // Show stored cookies in the console app.get('/listcookies', function(req, res){ console.log("Cookies : ", req.cookies); res.send('Look in console for cookies'); }); // Delete a cookie app.get('/deletecookie', function(req, res){ res.clearCookie('username'); res.send('username Cookie Deleted'); }); // Storing session information can be done in a few ways. // For development we can work with a memory store // Stores the session id in a cookie and the session data // on the server // npm install --save express-session var session = require('express-session'); // parseurl provides info on the url of a request object // npm install --save parseurl var parseurl = require('parseurl'); app.use(session({ // Only save back to the session store if a change was made resave: false, // Doesn't store data if a session is new and hasn't been // modified saveUninitialized: true, // The secret string used to sign the session id cookie secret: credentials.cookieSecret, })); // This is another example of middleware. app.use(function(req, res, next){ var views = req.session.views; // If no views initialize an empty array if(!views){ views = req.session.views = {}; } // Get the current path var pathname = parseurl(req).pathname; // Increment the value in the array using the path as the key views[pathname] = (views[pathname] || 0) + 1; next(); }); // When this page is accessed get the correct value from // the views array app.get('/viewcount', function(req, res, next){ res.send('You viewed this page ' + req.session.views['/viewcount'] + ' times '); }); // Reading and writing to the file system // Import the File System module : npm install --save fs var fs = require("fs"); app.get('/readfile', function(req, res, next){ // Read the file provided and either return the contents // in data or an err fs.readFile('./public/randomfile.txt', function (err, data) { if (err) { return console.error(err); } res.send("The File : " + data.toString()); }); }); // This writes and then reads from a file app.get('/writefile', function(req, res, next){ // If the file doesn't exist it is created and then you add // the text provided in the 2nd parameter fs.writeFile('./public/randomfile2.txt', 'More random text', function (err) { if (err) { return console.error(err); } }); // Read the file like before fs.readFile('./public/randomfile2.txt', function (err, data) { if (err) { return console.error(err); } res.send("The File : " + data.toString()); }); }); // Defines a custom 404 Page and we use app.use because // the request didn't match a route (Must follow the routes) app.use(function(req, res) { // Define the content type res.type('text/html'); // The default status is 200 res.status(404); // Point at the 404.handlebars view res.render('404'); }); // Custom 500 Page app.use(function(err, req, res, next) { console.error(err.stack); res.status(500); // Point at the 500.handlebars view res.render('500'); }); app.listen(app.get('port'), function(){ console.log('Express started on http://localhost:' + app.get('port') + '; press Ctrl-C to terminate'); }); |
main.handlebars
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<!DOCTYPE html> <html lang="en"> <head> <!-- References a Handlebars partial in views/partials/head.handlebars --> {{>head}} <title>Express Tutorial</title> </head> <body> <!-- References a Handlebars partial in views/partials/bsnavbar.handlebars --> {{>bsnavbar}} <!-- The HTML for each view goes here --> <div class="container"> {{{body}}} </div> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> </body> </html> |
.gitignore
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# Run npm init creates package.json which defines the # entry point as expresstut.js # Install Express by typing npm install --save express # in the terminal # Install the Express Handlebars package # npm install --save express-handlebars #ignore packages installed by npm node_modules *~ .DS_Store credentials.js # Create a Git repository with git init # Add files with 'git add -A' in the terminal # Commit the changes with 'git commit -m "Initial Commit"' |
credentials.js
1 2 3 |
// Used to encrypt cookies. Use a random string // Add this to .gitignore module.exports = { cookieSecret: 'force ability health couple', }; |
README.md
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 |
Express Tutorial : Describe Project Here ======= Sub-heading ----------- ### Another deeper heading Markdown is plain text formatting designed to convert to HTML Paragraphs are separated by a blank line. Leave 2 spaces at the end of a line to do a line break Text attributes *italic*, **bold**, `monospace`, ~~strikethrough~~ . A [link](http://example.com). Unordered list: * apples * oranges * pears Numbered list: 1. apples 2. oranges 3. pears |
bsnavbar.handlebars
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<div class="container"> <nav class="navbar navbar-default"> <div class="container-fluid"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="pull-left" href="#"><img src="/img/NTTLogosm.png"></a> </div> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active"><a href="/">Home <span class="sr-only">(current)</span></a></li> <li><a href="/about">About</a></li> <li><a href="/contact">Contact</a></li> <li><a href="/file-upload">File Upload</a></li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> </div> |
head.handlebars
1 2 3 4 5 6 7 |
<meta charset="UTF-8"> <!-- If IE use the latest rendering engine --> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- Set the page to the width of the device and set the zoom level --> <meta name="viewport" content="width = device-width, initial-scale = 1"> <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> |
The Views
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
------ 404.handlebars ------ <h3>404 : Not Found</h3> ------ 500.handlebars ------ <h3>500 : Server Error</h3> ------ about.handlebars ------ <div class="page-header"> <h3>About Us</h3> </div> ------ contact.handlebars ------ <div class="page-header"> <h3>Contact Us</h3> </div> <div class="contactUs"> <h4>Send Us your Questions</h4> <form class="formContactUs" role="form" action="/process?form=contactus" method="POST"> <input type="hidden" name="_csrf" value="{{csrf}}"> <div class="form-group"> <label for="fieldEmail" class="col-sm-2 control-label"> Email</label> <div class="col-sm-4"> <input type="text" class="form-control" id="fieldEmail" name="email"> </div> </div> <!-- End of form-group --> <div class="form-group"> <label for="fieldQues" class="col-sm-2 control-label"> Question</label> <div class="col-sm-4"> <input type="text" class="form-control" id="fieldQues" name="ques"> </div> </div> <!-- End of form-group --> <div class="form-group"> <div class="col-sm-4"> <button type="submit" class="btn btn-default">Submit</button> </div> </div> <!-- End of form-group --> </form> </div> <!-- End of contactUs --> ------ error.handlebars ------ <div class="page-header"> <h3>Something Went Wrong</h3> </div> ------ file-upload.handlebars ------ <form class="form-horizontal" role="form" enctype="multipart/form-data" method="POST" action="/file-upload/{year}/{month}"> <div class="form-group"> <label for="fieldName" class="col-sm-2 control-label"> Name </label> <div class="col-sm-4"> <input type="text" class="form-control" id="fieldName" name="name"> </div> </div> <div class="form-group"> <label for="fieldEmail" class="col-sm-2 control-label"> Email </label> <div class="col-sm-4"> <input type="email" class="form-control" required id="fieldEmail" name="email"> </div> </div> <div class="form-group"> <label for="fieldPhoto" class="col-sm-2 control-label"> Image</label> <div class="col-sm-4"> <!-- Only accept images --> <input type="file" class="form-control" required accept="image/*" id="fieldPhoto" name="photo"> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-4"> <button type="submit" class="btn btn-primary">Submit</button> </div> </div> </form> ------ home.handlebars ------ <div class="page-header"> <h3>Welcome to my Express Tutorial</h3> </div> ------ thankyou.handlebars ------ <div class="page-header"> <h3>Thank you for your Submission</h3> </div> |
Leave a Reply