# Welcome


# Install Node.js

This is Bevry's supported guide for installing [Node.js](http://nodejs.org/) on your computer as well as any other required dependencies for your particular system. This guide is Bevry's supported guide, as we've found other guides will leave you with an incorrectly configured environment causing permission errors and missing executables that are hard to track down.

## On Linux (Mac OSX, Ubuntu, Fedora, etc)

### Preparation

#### **Mac Preparation**

1. Install Command Line Tools:

   ```bash
   xcode-select --install
   ```

   Xcode may or may not be necessary for the above command, if it fails, [Download & Install Xcode](http://developer.apple.com/xcode/), and try again.
2. Ensure correct permissions are set for `/usr/local`:

   ```bash
   sudo chown -R $USER /usr/local
   ```

#### **APT Linux Preparation (Ubuntu)**

```bash
sudo apt-get update
sudo apt-get install curl build-essential openssl libssl-dev git python
```

#### **YUM Linux Preparation (Fedora)**

```bash
sudo yum -y install tcsh scons gcc-c++ glibc-devel openssl-devel git python
```

### Installation

[Node Version Manager aka NVM](https://github.com/creationix/nvm) lets you install multiple versions of Node.js to your local user directory, enabling easy upgrades and version switching, without the permission troubles that are common with non-NVM setups.

1. Uninstall any previous Node.js versions you may already have
2. Install NVM by running the following in Terminal:

   ```bash
   git clone git://github.com/creationix/nvm.git ~/.nvm
   printf "\n\n# NVM\nif [ -s ~/.nvm/nvm.sh ]; then\n\tNVM_DIR=~/.nvm\n\tsource ~/.nvm/nvm.sh\nfi" >> ~/.bashrc
   NVM_DIR=~/.nvm
   source ~/.nvm/nvm.sh
   ```
3. Install Node.js by running the following in Terminal:

   ```bash
   nvm install node
   nvm alias default node
   nvm use node
   ```

## On Windows

1. [Download & Install Git](http://git-scm.com/download)

   IMPORTANT. When installing, make sure you install with the option of making git available to the windows command line.
2. [Download & Install Node.js](https://nodejs.org/en/download/)


# Preface

{% embed url="<https://www.youtube.com/watch?v=_l96hPlqzcI&list=PLYVl5EnzwqsQs0tBLO6ug6WbqAbrpVbNf>" %}
Watch the recording of when this training was initially performed in 2012.
{% endembed %}

## Introduction

[Node.js](http://nodejs.org/) is an exciting platform for building web applications in JavaScript. With its unique I/O model, it excels at the sort of scalable and real-time situations we are increasingly demanding of our servers. The ability to use JavaScript for both the client and server opens up many possibilities for code sharing, expertise reuse, and rapid development. The class is intended for anyone looking to explore the capabilities of the Node.js development platform.

At the end of the class, students will have gained a grasp on node's ecosystem and paradigms, be able to write node modules that they can publish and share, and will have experimented with writing realtime web applications.

### Level Pre-Requisites

* Can write basic JavaScript code (script tags, functions, variables, HTML manipulation)
* Can write HTML and CSS - Understands form submission (client and server relationship)

### Required class materials / software

* Bring a laptop (any operating system that has a command line and a web browser is fine - e.g. Mac OSX, Windows, and Ubuntu)
* Have your system's build dependencies installed, as well as git and node. Need help? [Guide here.](https://app.gitbook.com/node/install)
* Source code editor installed ([Atom](https://atom.io) is what I use)

## Presenter

[Benjamin Lupton](http://balupton.com/) is the founder of [Bevry](http://bevry.me), an open-company and community dedicated to empowering developers everywhere. He has worked in web development since 2005, and specialised in JavaScript since 2009. He has created over 200 open-source JavaScript projects, which have been used in some of the world's biggest web-sites/apps (Basecamp, Spotify, Ustream) and by some of the world's biggest companies (Microsoft, Adobe, GitHub, Atlassian).


# What is Node.js

Node breaks JavaScript out of the box of the browser and brings it to the desktop to create remarkable new opportunities.

## Why should I care?

Before node, apps were generally like this:

* Naturally slow - operations happened in a blocking fashion
* No environment re-use - different people and code needed for back-end and front-end environments
* Limited - great for a particular subset of tasks (e.g. shell scripting or web pages) but require complex approaches for tasks outside that subset (e.g. RubyMotion and HipHop)

Node apps are more like this:

* Naturally fast - operations occur in an asynchronous and non-blocking fashion
* Environment re-use - people and code can be shared between back-end and front-end environments
* Powerful - great for a wide range of tasks out of the box (similar to Java and .NET)

## How is this possible?

These complimentary parts:

1. It is JavaScript. While JavaScript has its oddities, people can come to appreciate its flexibility and power. In that you can do whatever you want with it, the way you want, without limitations. This is testified by the AltJS community and JavaScript's vastness of different solutions to similar problems.
2. It is naturally asynchronous. JavaScript has a unique position as it allows you to code high-level asynchronous and non-blocking code while being aloof to the low-level technical challenges and implementations behind such a thing (aka threading). Writing asynchronous code is as easy as a callback function which anyone who has written a jQuery event handler already knows how to do.

Together, this allows node to offer non-blocking abilities easily and intuitively. As an example, this means you can read multiple files at the same time (in parallel) without blocking unnecessarily (waiting on something). In other languages, generally you would have to read the files one after the other (serially) waiting on each file to finish reading, before moving onto the next (blocking) - which is very slow. Now sure, non-blocking and parallel capabilities are in other languages, but you need a huge brain to understand how to write them correctly without shooting your foot off - javascript makes it as easy as writing a event handler or callback function with the underlying (and vastly unnecessary) complexity hidden away, making such power more accessible to the masses.

## Examples

The following examples showcase the fundamental differences between node and other languages. To bootstrap them, run the following in your terminal.

```bash
echo 'contents of one.txt' > one.txt
echo 'contents of two.txt' > two.txt
touch index.js
touch index.php
```

### Node

{% tabs %}
{% tab title="index.js" %}

```javascript
'use strict'

// Example 1
// output hello, then two seconds later output world
setTimeout(function () {
	console.log('world')
}, 2000)
console.log('hello')

// Example 2
require('fs').readFile('one.txt', function (err, data) {
	if (err) throw err
	console.log('contents:', data.toString())
})

// Example 3
require('fs').readFile('one.txt', function (err, data) {
	if (err) throw err
	console.log('one:', data.toString())
})
require('fs').readFile('two.txt', function (err, data) {
	if (err) throw err
	console.log('two:', data.toString())
})

// Example 4
// start a server
const server = require('http').createServer(function (req, res) {
    console.log('request received')
	res.writeHead(200, { 'Content-Type': 'text/plain' })
	res.end('Hello World\n')
}).listen({port: 8000, host: '127.0.0.1'}, _ => console.log('server listening'))
// close the server after 10 seconds
setTimeout(function () {
    server.close(_ => console.log('server closed'))
}, 10 * 1000)
```

{% endtab %}

{% tab title="one.txt" %}

```
contents of one.txt
```

{% endtab %}

{% tab title="two.txt" %}

```
contents of two.txt
```

{% endtab %}

{% tab title="bonus.js" %}

```javascript
'use strict'

// File Reader Class
class FileReader {

	// Read Files Asynchronously
	readFiles (files, next) {
		const results = []
		for (let i = 0, file, completed = 0; i < files.length; ++i) {
			file = files[i]
			require('fs').readFile(file, function (err, result) {
				// Check
				if (err) {
					i = files.length
					completed = files.length
					return next(err)
				}

				// Apply
				results.push(result.toString())

				// Check
				completed++
				if (completed === files.length) {
					return next(null, results)
				}
			})
		}
		return this
	}

	// Read Files Synchronously
	readFilesSync (files) {
		const results = []
		for (let i = 0, result, file; i < files.length; ++i) {
			file = files[i]
			try {
				result = require('fs').readFileSync(file)
			}
			catch (err) {
				throw err
			}
			// Apply
			results.push(result.toString())
		}
		return results
	}
}

// Read our files
const fileReader = new FileReader()
const files = ['one.txt', 'two.txt']

// Async
fileReader.readFiles(files, function (err, results) {
	if (err) throw err
	console.log('async:', results)
})

// Sync
const results = fileReader.readFilesSync(files)
console.log('sync:', results)
```

{% endtab %}
{% endtabs %}

{% embed url="<https://glot.io/snippets/f6fvue94ky>" %}
Run the earlier Node.js snippet.
{% endembed %}

### PHP

{% tabs %}
{% tab title="index.php" %}

```php
<?php

# Example 1
echo "hello\n";
sleep(2);  # sleeps for 2 seconds
echo "world\n";

# Example 2
$contents = file_get_contents('one.txt');
if ( $contents === false ) {
	echo "error occured\n";
	exit(-1);
} else {
	echo "contents: $contents\n";
}

# Example 3
$one = file_get_contents('one.txt');
$two = file_get_contents('two.txt');
if ( $one === false || $two === false ) {
	echo "error occured\n";
	exit(-1);
} else {
	echo "one: $one\n";
	echo "two: $two\n";
}

# Example 4
# Not possible in PHP

```

{% endtab %}

{% tab title="one.txt" %}

```
contents of one.txt
```

{% endtab %}

{% tab title="two.txt" %}

```
contents of two.txt
```

{% endtab %}
{% endtabs %}

{% embed url="<https://glot.io/snippets/f6fvlz15y6>" %}
Run the earlier PHP snippet.
{% endembed %}

## Caution

Beware of these things:

1. Adding asynchronous flow to an entirely synchronous program will cause you to have to re-write your application. You are better off just jumping the learning hurdle of asynchronous code at the start. For example, so far you have written your application all with synchronous calls because it was easier, then at some point, you needed to do an asynchronous call, this causes a break in your flow that requires all future execution in your application to operate asynchronously.
2. Adding synchronous flow to an asynchronous program will require some flow control management (there are plenty of flow control libraries you can use to alleviate this complexity). For example, if you want to perform multiple tasks in parallel, but once they have all completed, then move onto the next task.

These are not issues found in naturally synchronous languages, as they do not have the benefit of asynchronous flow to begin with.


# Node's Ecosystem

## Core

Node was created by [Ryan Dahl](https://github.com/ry). Then it was maintained by [Joyent](http://joyent.com/). Now it is maintained by the [Node.js Foundation](https://nodejs.org/en/foundation/). Node is open-source and [located on github](http://github.com/nodejs/node). [Anyone can contribute to shape its future.](https://nodejs.org/en/get-involved/)

The mission of the core is to be as lightweight as possible. If a module can do something, then it won't make it into the core.

## Programs

Executing node code is as easy as running `node your-node-file`. To make use of other modules, you will want to write a `package.json` file in the root directory of your program. This file is used to define your application, including information such as its name, description, environments it can run under, and any modules it is dependent on. If you decide to publish your program to the world (making it a module others can use) then you will require a `package.json` file.

A typical `package.json` will look like this:

{% code title="package.json" %}

```javascript
{
  "name": "my-program",
  "version": "1.0.0",
  "description": "program description",
  "homepage": "http://programs-website.com",
  "keywords": [
    "one",
    "two",
    "three"
  ],
  "author": "Bevry Pty Ltd <us@bevry.me> (http://bevry.me)",
  "maintainers": [
    "Benjamin Lupton <b@lupton.cc> (http://balupton.com)"
  ],
  "contributors": [
    "Benjamin Lupton <b@lupton.cc> (http://balupton.com)"
  ],
  "bugs": {
    "url": "http://programs-issue-tracker.com"
  },
  "repository": {
    "type": "git",
    "url": "http://programs-repository.git"
  },
  "engines": {
    "node": ">=0.6.0",
    "npm": ">=1.1.0"
  },
  "dependencies": {
    "connect": "2.6.x",
    "express": "3.0.x",
    "socket.io": "0.9.x"
  },
  "devDependencies": {
    "coffee-script": "1.4.x"
  },
  "directories": {
    "lib": "./lib"
  },
  "bin": {
    "program": "./bin/program"
  },
  "scripts": {
    "test": "node ./test/everything.test.js"
  },
  "main": "./main.js"
}
```

{% endcode %}

A lot is defined here; [the best way to discover their meanings is by referring to specification on the npmjs website.](https://docs.npmjs.com/files/package.json)

> If you are writing a program that you never want to be released to the outside world, you will want to add `"private": true` as well. This will tell npm to never publish your program even if someone accidentally runs `npm publish`.

## Modules

Modules are just like programs, except the author has decided to publish them to the world using [npm](https://npmjs.com) - whose website includes a directory of all the published modules for you surf and discover.

* To publish your program as a module, run `npm publish` in your program's directory
* To use a module in your program, you first install it to your program using `npm install <module-name>`, then you can use it in your code by doing `var theModule = require('module-name');`
* To install a module globally (so you can utilise its executables if it has any) you will use `npm install -g <module-name>`

Modules will generally abide by [semantic versioning rules](http://semver.org/), npm also supports semver ranges, this allows you to increase compatability by doing:

1. `{ "dependencies": {"some-dependency": "~1.2.3"} }` which will accepted all v1.2 versions of that dependency that are v1.2.3 or higher
2. `{ "dependencies": {"some-dependency": "^1.2.3"} }` which will accepted all v1 versions of that dependency that are v1.2.3 or higher

Both of these are better than just doing `"1.2.3"` directly, as it decreases maintenance when new versions come out which are often compatible depending on the module authors practices.

Never specify a range that has no upper limit, such as `>=1` or `*` as soon enough, the module will publish a breaking change that will break your app. Hence why semver exists.

If you are building a mission critical app, you can use [shrinkwrap](https://docs.npmjs.com/cli/shrinkwrap) and/or [bundled dependencies](https://docs.npmjs.com/files/package.json#bundleddependencies) to help guarantee stability, even while using version ranges.

## Discovering Modules

The [npm website](https://npmjs.org/) is the best place for discovering all the modules. Good modules generally have:

1. Modules that already use it (called dependents) - found on the npm website in the right sidebar
2. Tests that guarantee it runs well — found in the source code repository of the module

Earlier than 2014, "last update" was also a factor to judge, however since 2015, node.js has minimised breaking changes allowing small modules that do a few things well to go unchanged over the years while continuing to work splendidly.


# Simple Servers

## Basic Server

{% code title="server-basic.js" %}

```javascript
'use strict'

const http = require("http")
let count = 0
http.createServer(function(req, res) {
    const message = `Received ${++count} requests so far`
    console.log(message)
    res.writeHead(200, { "Content-Type": "text/plain" })
    res.end(message)
})
.listen(8080)
```

{% endcode %}

Run it: `node server-basic.js`

Test it: `curl http://localhost:8080`

## Server with Pause

{% code title="server-pause.js" %}

```javascript
'use strict'

const http = require('http')
http.createServer(function (req, res) {
	res.writeHead(200, { 'Content-Type': 'text/plain' })
	res.write('hello\n')
	setTimeout(function () {
		res.end('world\n')
	}, 2 * 1000)
}).listen(8080)

```

{% endcode %}

Run it: `node server-pause.js`

Bench it: `ab -n 100 -c 100 http://localhost:8080/`

## Echo Server

{% code title="server-echo.js" %}

```javascript
'use strict'

const net = require('net')
net.createServer(function (socket) {
	socket.write('Talk to me.\n')
	socket.on('data', function (data) {
		socket.write(data.toString().toUpperCase())
	})
}).listen(8080)
```

{% endcode %}

Run it: `node server-echo.js`

Talk with it: `nc localhost 8080`

## Chat Server

{% code title="server-chat.js" %}

```javascript
'use strict'

// Application
const net = require('net')
let sockets = []
net.createServer(function (socket) {
	sockets.push(socket)
	socket.write('Talk to me.\n')

	socket.on('data', function (data) {
		for (let i = 0; i < sockets.length; ++i) {
			sockets[i].write(data)
		}
	})

	socket.on('end', function () {
		const index = sockets.indexOf(socket)
		sockets = sockets.slice(0, index).concat(sockets.slice(index + 1))
	})
}).listen(8080)
```

{% endcode %}

Run it: `node server-chat.js`

Talk with it: `nc localhost 8000`

## Supplemental

### Echo Server with Transform Stream

{% code title="server-echo-transform.js" %}

```javascript
'use strict'

class UC extends require('stream').Transform {
	_transform (data, encoding, next) {
		next(null, data.toString().toUpperCase())
	}
}

class Reverse extends require('stream').Transform {
	_transform (data, encoding, next) {
		next(null, data.toString().split('').reverse().join(''))
	}
}

require('net').createServer(function (socket) {
	socket.write('Talk to me.\n')
	socket.pipe(new UC()).pipe(new Reverse()).pipe(socket)
}).listen(8080)
```

{% endcode %}

Run it: `node server-echo-transform.js`

Talk with it: `nc localhost 8080`

### Chat Server with Extras

{% code title="server-chat-extra.js" %}

```javascript
'use strict'

// Application
const net = require('net')
let count = 0
const sockets = {}
function broadcast (message) {
	for (const key in sockets) {
		if (sockets.hasOwnProperty(key)) {
			sockets[key].write(message)
		}
	}
}
net.createServer(function (socket) {
	sockets[socket.index = count++] = socket
	socket.write('Hello user ' + socket.index + '\n')
	broadcast('User ' + socket.index + ' joined\n')

	socket.on('data', function (data) {
		broadcast('User ' + socket.index + ' says: ' + data.toString())
	})

	socket.on('end', function () {
		delete sockets[socket.index]
		broadcast('User ' + socket.index + ' left\n')
	})
}).listen(8080)
```

{% endcode %}

Run it: `node server-chat-extra.js`

Talk with it: `nc localhost 8080`


# Advanced Servers

## Static File Server

One popular use case is to serve files directly from a directory on our machine.

For this, we will setup a configuration module at `config.js` that contains:

{% code title="config.js" %}

```javascript
'use strict'

module.exports = {
	staticPath: __dirname  // process.cwd()
}
```

{% endcode %}

Which our application will include via `require('./config')` (extensions are optional).

### Read File

The most basic way of accomplishing this, is to use [fs.readFile](https://nodejs.org/dist/latest-v5.x/docs/api/fs.html#fs_fs_readfile_file_options_callback)

{% code title="server-readfile.js" %}

```javascript
'use strict'

// Requires
const httpUtil = require('http')
const fsUtil = require('fs')
const pathUtil = require('path')
const urlUtil = require('url')
const config = require('./config')

// Server
httpUtil.createServer(function (req, res) {
	const file = urlUtil.parse(req.url).pathname
	const path = pathUtil.join(config.staticPath, file)
	fsUtil.exists(path, function (exists) {
		if (!exists) {
			res.statusCode = 404
			return res.end('404 File Not Found')
		}
		fsUtil.readFile(path, function (error, data) {
			if (error) {
				console.log('Warning:', error.stack)
				res.statusCode = 500
				return res.end('500 Internal Server Error')
			}
			return res.end(data)
		})
	})
}).listen(8080)
```

{% endcode %}

Test it: `curl http://localhost:8080/server-static.js`

However, readFile will read the entire file, then send the entire file. Take a moment to imagine how this not optimum.

### Streams

The next most basic way, is to use a [Readable Stream](https://nodejs.org/dist/latest-v5.x/docs/api/stream.html#stream_class_stream_readable) via [fs.createReadStream](https://nodejs.org/dist/latest-v5.x/docs/api/fs.html#fs_fs_createreadstream_path_options).

{% code title="server-stream.js" %}

```javascript
'use strict'

// Requires
const httpUtil = require('http')
const fsUtil = require('fs')
const pathUtil = require('path')
const urlUtil = require('url')
const config = require('./config')

// Server
httpUtil.createServer(function (req, res) {
	const file = urlUtil.parse(req.url).pathname
	const path = pathUtil.join(config.staticPath, file)
	fsUtil.exists(path, function (exists) {
		if (!exists) {
			res.statusCode = 404
			return res.end('404 File Not Found')
		}
		const read = fsUtil.createReadStream(path)
		read.on('error', function (error) {
			console.log('Warning:', error.stack)
			res.statusCode = 500
			return res.end('500 Internal Server Error')
		})
		read.pipe(res)
	})
}).listen(8080)
```

{% endcode %}

Test it: `curl http://localhost:8080/server-static.js`

### Directories

Getting more advanced here. What about outputting the contents of directories too? For this, we can use [fs.readdir](https://nodejs.org/dist/latest-v5.x/docs/api/fs.html#fs_fs_readdir_path)

{% code title="server-static.js" %}

```javascript
'use strict'

// Requires
const httpUtil = require('http')
const fsUtil = require('fs')
const pathUtil = require('path')
const urlUtil = require('url')
const config = require('./config')

// @TODO
// This is getting a bit big, how can we refactor this?
// Can we abstract it out?
// What considerations do we need to take into account?
// How would we add additional actions if we abstract?

// Server
httpUtil.createServer(function (req, res) {
	const file = urlUtil.parse(req.url).pathname
	const path = pathUtil.join(config.staticPath, file)
	fsUtil.exists(path, function (exists) {
		if (!exists) {
			res.statusCode = 404
			return res.end('404 File Not Found')
		}
		fsUtil.stat(path, function (error, stat) {
			if (error) {
				console.log('Warning:', error.stack)
				res.statusCode = 500
				return res.end('500 Internal Server Error')
			}

			if (stat.isDirectory()) {
				fsUtil.readdir(path, function (error, files) {
					if (error) {
						console.log('Warning:', error.stack)
						res.statusCode = 500
						return res.end('500 Internal Server Error')
					}
					return res.end(files.join('\n'))
				})
			}
			else {
				const read = fsUtil.createReadStream(path)
				read.on('error', function (error) {
					console.log('Warning:', error.stack)
					res.statusCode = 500
					return res.end('500 Internal Server Error')
				})
				read.pipe(res)
			}
		})
	})
}).listen(8080)
```

{% endcode %}

Test it: `curl http://localhost:8080`

## Applying Abstractions

Considering the static file server example is incredibly common. Lets think of ways we can abstract out the serving of static files so we can re-use that functionality easily.

Desiring a solution like:

{% code title="server-static-module.js" %}

```javascript
'use strict'

// Requires
const httpUtil = require('http')
const serveStatic = require('./serve-static')
const config = require('./config')

// Server
httpUtil.createServer(function (req, res) {
	serveStatic(config.staticPath, req, res)
}).listen(8080)

// Can even do this, due to the simplicity
// httpUtil.createServer(
// 	serveStatic.bind(null, config.staticPath)
// ).listen(8080)
```

{% endcode %}

One could come up with the following:

{% code title="serve-static.js" %}

```javascript
'use strict'

// Requires
const fsUtil = require('fs')
const pathUtil = require('path')
const urlUtil = require('url')

// Serve static
module.exports = function (root, req, res, next) {
	const file = urlUtil.parse(req.url).pathname
	const path = pathUtil.join(root, file)
	fsUtil.exists(path, function (exists) {
		if (!exists) {
			if (next) return next()
			res.statusCode = 404
			return res.end('404 File Not Found')
		}
		fsUtil.stat(path, function (error, stat) {
			if (error) {
				console.log('Warning:', error.stack)
				res.statusCode = 500
				return res.end('500 Internal Server Error')
			}

			if (stat.isDirectory()) {
				fsUtil.readdir(path, function (error, files) {
					if (error) {
						console.log('Warning:', error.stack)
						res.statusCode = 500
						return res.end('500 Internal Server Error')
					}
					return res.end(files.join('\n'))
				})
			}
			else {
				const read = fsUtil.createReadStream(path)
				read.on('error', function (error) {
					console.log('Warning:', error.stack)
					res.statusCode = 500
					return res.end('500 Internal Server Error')
				})
				read.pipe(res)
			}
		})
	})
}

```

{% endcode %}

Note the introduction of a `next` callback. This allows us to chain additional or custom functionality.

{% code title="server-static-custom.js" %}

```javascript
'use strict'

// Requires
const httpUtil = require('http')
const serveStatic = require('./serve-static')
const config = require('./config')

// Server
httpUtil.createServer(function (req, res) {
	serveStatic(config.staticPath, req, res, function () {
		res.statusCode = 404
		res.end('404 Not Found. 🙁 \n')
	})
}).listen(8080)
```

{% endcode %}

## Introduction to Middlewares

In our previous example of writing the `serveStatic` what we effectively did was create a middleware, albiet a basic middleware but a middleware nonetheless. Naturally, there are already [plenty of other middlewares](https://npmjs.org/browse/keyword/middleware) published as modules by other people. This is helped by the middleware framework [Connect](http://senchalabs.org/connect/) originally by [TJ Holowaychuk](https://github.com/visionmedia).

Before we can install anything, we need to first initialise our directory as a node.js project:

```
npm init
```

That will create a `package.json` file that will keep track of the dependencies we install.

We can install connect like so:

```bash
npm install --save connect
```

Using connect, our static file server example would become:

{% code title="connect-static.js" %}

```javascript
'use strict'

// Requires
const connect = require('connect')
const config = require('./config')

// Server
const app = connect()

// Middlewares

// Use our local static middleware
app.use(require('./serve-static').bind(null, config.staticPath))

// Create the fallback middleware for when the route was not found
app.use(function (req, res) {
	res.statusCode = 404
	res.end('404 Not Found. 🙁 \n')
})

// Listen
app.listen(8080)
```

{% endcode %}

Much simpler. Notice how the middlewares are like a waterfall, it hits the first, then if the first doesn't know what to do, the logic will flow through to the next middleware (accomplished by the previous middleware calling the `next` callback inside it).

Connect has plenty of other middlewares available for it. [Official middlewares for connect are listed on its website](http://www.senchalabs.org/connect/) with [3rd party middleware listed on GitHub](https://github.com/senchalabs/connect/wiki).

There is even existing middlewares for what we've just accomplished. We can install them like so:

```
npm install --save serve-static serve-index
```

And consume them like so:

{% code title="connect-community.js" %}

```javascript
'use strict'

// Requires
const connect = require('connect')
const config = require('./config')

// Server
const app = connect()

// Middlewares

// Serve the files at the static path
app.use(require('serve-static')(config.staticPath))

// If a directory is requested, serve its index.html file if it has one
app.use(require('serve-index')(config.staticPath))

// If none of the previous middlewares matched, then fallback to 404
app.use(function (req, res) {
	res.statusCode = 404
	res.end('404 Not Found. 🙁 \n')
})

// Listen
app.listen(8080)
```

{% endcode %}

## Introduction to Web Frameworks

There are a [few web frameworks for node](http://stackoverflow.com/questions/3809539/choosing-a-web-application-framework-using-node-js). The most used is [Express](http://expressjs.com/) originally by [TJ Holowaychuk](https://github.com/visionmedia).

> Perhaps by now you would have noticed the amount of individuals mentioned who have created awesome things, this is very much the case, anyone can have an impact.

Express can be thought of as a layer that sits ontop of connect and node's http module. It provides its own middleware and uses its own request and response objects that inherit from those of node's http module. The benefit over just using connect are:

* Addition of routing
* Common functionality provided through a friendly syntax

We can install express like so:

```bash
npm install --save express
```

The following is what a simple hello world server would look like with express:

{% code title="express-basic.js" %}

```javascript
'use strict'

// Requires
const express = require('express')

// Application
const app = express()

// Routes
// These make things easier
app.get('/', function (req, res) {
	res.send('hello world')
})

// Fallback middleware
app.use(function (req, res) {
	res.send(404, '404 Not Found. 🙁 \n')
	// ^ this is different from connect
})

// Server
const server = app.listen(8080)
```

{% endcode %}

> It is important to note that the line `var server = app.listen(8080);` is the same as doing `var server = require('http').createServer(app).listen(8080);`. You will need to remember this when interfacing with other modules - some modules like to interface with the express instance `app` while others like to interface with the node http server instance `server` instead.

And this is what our static file server will look like with express:

{% code title="express-static.js" %}

```javascript
'use strict'

// Requires
const express = require('express')
const config = require('./config')

// Application
const app = express()

// Middlewares

// Use our local one
app.use(require('./serve-static').bind(null, config.staticPath))

// Use the prexisting ones
// app.use(require('serve-static')(config.staticPath))
// app.use(require('serve-index')(config.staticPath))

// Fallback middleware
app.use(function (req, res) {
	res.send(404, '404 Not Found. 🙁 \n')
})


// Server
const server = app.listen(8080)

```

{% endcode %}

Notice the nicer syntax for setting the status code of the response. Before it was `res.statusCode = 404;` now it is the first argument of `res.send`. This is what we meant by express providing a nicer syntax.


# Web Applications

## Building a Chat Web Application

It's now time to move onto building a proper web application. Rather than the simple todo application you would build in other systems, for node the standard is a chat application (which is a lot more exciting!).

To do this, we will use [Primus](https://github.com/primus/primus) and [ws](https://github.com/websockets/ws) both by [Arnout Kazemier](https://github.com/3rd-Eden).

Primus is a wrapper library over many different [WebSockets](https://en.wikipedia.org/wiki/Websocket) libraries. WebSockets is a technology that allows browser clients to communicate with servers. Until WebSockets became a thing in 2011, such functionality was achieved via [several dodgy workarounds](http://slides.com/balupton/what).

We can install Primus for our project like so:

```bash
npm init  # setup our project
npm install --save express  # install express, which we will attach Primus to
npm install --save primus  # install Primus
npm install --save ws  # the WebSockets library we will sue with Primus
```

### Server to Browser Relay

The most basic example of this is the following, which will allow the server to broadcast to all clients, while receiving responses from clients:

{% tabs %}
{% tab title="socket-server.js" %}

```javascript
'use strict'

// Requires
const express = require('express')
const Primus = require('primus')
const pathUtil = require('path')

// Application
const app = require('express')()
const server = require('http').createServer(app)
const primus = new Primus(server, { transformer: 'websockets' })

// Middlewares
app.get('/', function (req, res) {
	require('fs').createReadStream(pathUtil.join(__dirname, 'socket-client.html')).pipe(res)
})
app.use(function (req, res) {
	res.status(404).send('404 Not Found. 🙁 \n')
})

// Socket
primus.on('connection', function (spark) {
	console.log('connection has the following headers', spark.headers)
	console.log('connection was made from', spark.address)
	console.log('connection id', spark.id)

	// Receive messages
	spark.on('data', function (message) {
		console.log('connection', spark.id, 'sends', message.toString())
	})

	// Send messages
	process.stdin.on('data', function (message) {
		spark.write('The server has spoken: ' + message.toString())
	})

	// Send an initial hello
	spark.write('Hello user. I am the server communicating to you.')
})

// Listen
server.listen(8080)
```

{% endtab %}

{% tab title="socket-client.html" %}

```markup
<!DOCTYPE html>
<html>

<head>
	<title>My Web App</title>
</head>

<body>
	<!-- Scripts -->
	<script src="/primus/primus.js"></script>
	<script>
		// Tell primus to create a new connect to the current domain/port/protocol
		var primus = new Primus()

		// Ask for a response if we receive data
		primus.on('data', function (message) {
			alert(message)
			var response = prompt('What would you like to say?')
			if (response) {
				primus.write(response)
				alert('Sent')
			}
		})
	</script>
	Hello.
</body>

</html>
```

{% endtab %}
{% endtabs %}

Test it: <http://localhost:8080/>

### Browser to Browser Broadcasting

A more useful example of this, is your basic chat app, which allows clients to broadcast to other clients:

{% tabs %}
{% tab title="chat-server.js" %}

```javascript
'use strict'

// Requires
const express = require('express')
const Primus = require('primus')
const pathUtil = require('path')

// Application
const app = require('express')()
const server = require('http').createServer(app)
const primus = new Primus(server, { transformer: 'websockets' })

// Middlewares
app.get('/', function (req, res) {
	require('fs').createReadStream(pathUtil.join(__dirname, 'chat-client.html')).pipe(res)
})
app.use(function (req, res) {
	res.status(404).send('404 Not Found. 🙁 \n')
})

// Socket
primus.on('connection', function (spark) {
	console.log('connection has the following headers', spark.headers)
	console.log('connection was made from', spark.address)
	console.log('connection id', spark.id)

	// Receive messages
	spark.on('data', function (message) {
		// Broadcast them back to everyone
		primus.write('user ' + spark.id + ' sends ' + message.toString())
	})

	// Send an initial hello
	spark.write('Hello user ' + spark.id + '. I am the server communicating to you.')
})

// Listen
server.listen(8080)
```

{% endtab %}

{% tab title="chat-client.html" %}

```markup
<!DOCTYPE html>
<html>

<head>
	<title>My Web App</title>
	<style>
		.messages {
			max-height: 500px;
			border: 1px solid gray;
			overflow: auto;
		}
		.messageInput {
			width: 100%;
			padding: 1em;
		}
	</style>
</head>

<body>
	<!-- App -->
	<div class="app">
		<ul class="messages"></ul>
		<input type="text" disabled class="messageInput" placeholder="Enter your message here" />
	</div>

	<!-- Scripts -->
	<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-beta1/jquery.min.js"></script>
	<script src="/primus/primus.js"></script>
	<script>
		// Tell primus to create a new connect to the current domain/port/protocol
		var primus = new Primus()

		// Ready
		$(function () {
			// Fetch
			var $app = $('.app')
			var $messages = $app.find('.messages')
			var $messageInput = $app.find('.messageInput')

			// Enable input once connection is open
			primus.on('open', function () {
				$messageInput.removeAttr('disabled').focus()
			})

			// Receive message
			primus.on('data', function (message) {
				$message = $('<li>', {
					'class': 'message',
					text: message
				})
				$messages.append($message)
			})

			// Send message
			$messageInput.on('keypress', function (event) {
				if (event.keyCode === 13) {  // enter
					var message = $messageInput.val().trim()
					primus.write(message)
					$messageInput.val('')  // clear input
				}
			})
		})
	</script>
</body>

</html>
```

{% endtab %}
{% endtabs %}

Test it: <http://localhost:8080/>

## Where can this go?

It is now your turn to have a go and mash up your own solution. To help you get started, here are a bunch of ideas on how you can extend the chat application:

* Chat Rooms
  * Add support for two chat rooms
  * Add support for unlimited chat rooms
  * Allow users to change the names of the chat rooms
* Users
  * Give each user a randomly generated name - e.g. `User ${Math.random()}`
  * Next to each message, show the user who sent it - e.g.`${user.name} says: ${message.text}`
  * Show user connection and disconnection events as messages in the chat - e.g. `${user.name} joined the chat"`
  * Remember the user's details if they leave the page and come back - e.g. localstorage or sessions
  * Allow the user to change their name
  * Show user name change events as messages in the chat - e.g.`${oldName} changed their name to ${newName}`
  * Give each user their own randomly selected color - e.g. `style="color: hsl(50,50,50);"`
  * Create a sidebar that lists all active members in the chat room
  * Allow users to specify their email
  * If a user has an email specified, display their avatar next to their username in the message listing
  * When a user changes their details, automatically update all prior mentions of their details
* Abstractions
  * Experiment with pre-processors - [DocPad](http://docpad.org) could help with this
* Messages
  * Relative times
  * Markdown support
  * Webkit notifications


# Appendix

Thank you to [General Assembly](http://generalassemb.ly/) in October 2012 and [Codemaster Institute](http://www.codemasterinstitute.com) in April 2016 for hosting this training.

Follow [Benjamin Lupton](http://balupton.com) on [Twitter](https://twitter.com/balupton) and [GitHub](https://github.com/balupton).

## Resources

### Talks

* [Introduction to Node.js with Ryan Dahl](http://www.youtube.com/watch?v=jo_B4LTHi3I) - a bit aged, but still good
* [Evented Ruby vs Node.js by Jerry Cheung](http://www.youtube.com/watch?v=jo_B4LTHi3I) - good comparison about how node and ruby's approach to asynchrony differs
* [Programming Style and Your Brain](http://www.youtube.com/watch?v=prAwkQt3ARg) - on how error prevention is better than cleverness (the reason why I love CoffeeScript for the most part but hate CoffeeScript's implicit returns)

### Further Learning

* [Node School](http://nodeschool.io) - [balupton's answers](https://github.com/balupton/nodeschools) (don't cheat)
* [Joyent's Guides](https://www.joyent.com/developers/node)
* [Exception Handling in Node](http://stackoverflow.com/a/7313005/130638)
* [Debugging & Profiling Node.js](http://stackoverflow.com/a/16512303/130638)
* [Comprehensive Node.js Training](https://gist.github.com/balupton/8d5dda4cd1c72490cdc354e00d528a9e)
* [Node Fail Safe](https://github.com/bevry/nodefailsafe)

### Recommended Modules

* Async
  * [TaskGroup](https://github.com/bevry/taskgroup)
  * [Async.js](https://github.com/caolan/async)
* Testing
  * [Joe](https://github.com/bevry/joe)
  * [Chai](http://chaijs.com/)
* Querying
  * [QueryEngine](https://github.com/bevry/query-engine/)
* Templating
  * [ECO](https://github.com/sstephenson/eco) to HTML
  * [Stylus](http://learnboost.github.com/stylus/) to CSS
  * [CoffeeScript](http://coffeescript.org/) to JavaScript
  * [Babel](https://babeljs.io) for ESNext to ES2015
* Servers
  * [Connect](http://www.senchalabs.org/connect/)
  * [Express](http://expressjs.com)
  * [Session Middlewares](http://stackoverflow.com/a/13049549/130638)
* Configuration Files
  * [CSON](https://github.com/bevry/cson)
  * [YAML.js](https://github.com/jeremyfa/yaml.js)
* Utilities
  * [Lodash](https://lodash.com)
  * [SafePS](https://github.com/bevry/safeps)
  * [SafeFS](https://github.com/bevry/safefs)
  * [Eachr](https://github.com/bevry/eachr)
  * [Extendr](https://github.com/bevry/extendr)
  * [Watchr](https://github.com/bevry/watchr)
  * [Request](https://github.com/mikeal/request)
* CLI
  * [Caterpillar](https://github.com/bevry/caterpillar)
  * [Vorpal](http://vorpal.js.org)
* Robotics
  * [NodeCopter](http://nodecopter.com/)


# Glossary

* Front-end - browser based environment (think HTML, CSS, jQuery)
* Back-end - desktop and server based environment (Ruby, Rails)
* Scripting language - language which default implementations run then die (Perl, Python, PHP, Ruby)
* Compilation language - language which default implementation stays alive (Java, C)
* Blocking - waiting for something to complete and not being able to do other things (waiting in line)
* Non-Blocking - waiting for something to complete and being able to do other things while you wait (waiting via callout system)
* Asynchronous - able to break off from the main flow of doing something (fork in a river)
* Synchronous - stays with the main flow (curve in a river)
* Parallel - multiple things happening at the same time (multi-tasking)
* Serial - things happen in order, one after the other (single-tasking)
* AltJS - languages that aren't javascript but become javascript through a compilation/transformation process (CoffeeScript)
* High-level - abstractions have obscured away the difficulties and challenges into a nice interface
* Low-level - you're provided with the bare minimum, difficulties and challenges are solved by you
* API (Application Programming Interface) - the things you call to do something with something


