93
Introduction to Node.js

NodeJS

Embed Size (px)

Citation preview

Page 1: NodeJS

Introduction to Node.js

Page 2: NodeJS

Whoami

Giovanni LelaCTO@LinkMecofounder@MeanMilan@lambrojoshttp://github.com/lambrojos

Page 3: NodeJS

Logistics

● Text editor● node.js >= 0.10.*● npm

● nodeschool.io

Page 4: NodeJS

Brief history of server side js

Pre-nodejs● Netscape enterprise server (1994)● IIS (1996)Not very successful

Page 5: NodeJS

Enter node.js

● Ryan Dahl creates node.js to easily give sites push capabilities

● 2009 - Birth of node.js● Joyent takes control

Page 6: NodeJS

Hype, dissatisfaction, forks

In the following years node gains substantial traction.But in 2014 project stagnation leads to a fork - io.jsWhat now?

Page 7: NodeJS

Node.js foundation

Node is currently sponsored by the node.js foundation, with some big names being listed in the sponsors.

The node.js foundation itself is hosted by the linux foundation.

Technical decisions are made by the Tecnical Steering Commitee

Page 8: NodeJS

Why node.js matters

It can handle a lot of concurrent I/O operations.This is because of non-blocking I/O and javascript own nature.

Page 9: NodeJS

Blocking I/O analogy

Suppose you own a fast-food restaurant:● the cashier takes the order than waits for the food

to be ready before doing anything else

● if you want to serve more customers you need more cashiers

● this is “classical” multi-threaded parallel execution

Page 10: NodeJS

Non blocking I/O analogy

- As soon as you place your order, it’s sent off for someone to fulfill while the cashier is still taking your payment.

- When you are done paying, you have to step aside because the cashier is already looking to service the next customer.

- When your order is complete, you will be called back

Page 11: NodeJS

In real life

- the node server receives a request for /about.html

- while node waits for the filesystem to get the file, the server thread services the next

- when the file is ready a callback function call is inserted in the server thread message queue - can be seen as a todo list

Page 12: NodeJS

Everything runs in parallel, except your code

source: http://localhost:9000/images/event-loop.jpg

Page 13: NodeJS

Event loops

There are event loop implementations for many languages in platform. But in node.js the event loop is the platform

Page 14: NodeJS

One last diagram

Page 15: NodeJS

What not to do in the event loop

Everything that is CPU- intensive:● image / video processing● heavy number crunching● compressing files● actually everything involving complex

algorithms(Hower you can write native extensions)

Page 16: NodeJS

What do - remote APIs

● REST/JSON Api● quite fun to use node with non relational DB● lots of stable and mature frameworks:

○ Express○ Hapi○ Sails.js○ Loopback○ ...

Page 17: NodeJS

Javascript everywhere

● also your frontend can be in javascript● the barriers between the front and the back

end look thinner - Isomorphism● Shared rendering● Shared models

Page 18: NodeJS

Real time web apps

That what it was born for● Frameworks:

○ Primus○ Socket IO○ Meteor

● It can also be integrated inside an existing web stack

Page 19: NodeJS

IoT applications

● Hardware ○ Arduino○ Rasperry PI○ ..

● Frameworks○ johnny five (robotics)○ node-red (visual integration)○ ...

Page 20: NodeJS

Desktop applications

Electron by github is a framework for building desktop apps. Applications built on Electron include:● Atom ● Slack clients● Visual studio code● Kitematic (docker)

Page 21: NodeJS

Differences from the browser

● No DOM ● No browser globals such as window, document● No browser inconsistencies - you just have the

v8● ES5 supported - no ugly hacks and polyfills● ES6 getting supported

Page 22: NodeJS

Something you don’t have in the browser

● control over the process● streams● dependency management● lots of callbacks

Page 23: NodeJS

Process

It is a global variable it allow us to interct with the OS● process.exit(code)● process.env.[env variable name]● process.argv - read command line

parameters $ node argv.js one two three four myArgs: [ 'one', 'two', 'three', 'four' ]

Page 24: NodeJS

Node streams

● They emit events which represent I/O operations

● They can be readable, writable or both (duplex)

Page 25: NodeJS

Node streams: example

var readable = getReadableStreamSomehow();

readable.on('data', function(chunk) {

console.log('got %d bytes of data', chunk.length);});

readable.on('end', function() {

console.log('there will be no more data.');});

Page 26: NodeJS

Combining streams w/ pipe

var fs = require('fs');var readableStream = fs.createReadStream('file1.txt');var writableStream = fs.createWriteStream('file2.txt');readableStream.pipe(writableStream);

Page 27: NodeJS

Modules

Modules are managed with common.jsexports.getGreetings = function() {

return 'Hello World';};

//example.jsvar hello = require('./hello.js');var greetings = hello.getGreetings();

Page 28: NodeJS

Module management: NPM

Common js modules are installed with npm● npm install● npm uninstall● npm updateaModules can be installed globally (applications), or locally to your applications (dependencies).

Page 29: NodeJS

Dependency management

Your application dependencies and their version are listed in the package.json files.It can store other informations such as version, author, scripts to be executed during the application lifecycle.

Page 30: NodeJS

Node-style callbacks

a.k.a. Error-first callbacks a.k.a. Nodebacks

function callback (err, data) { /* ... */ }

Beware of callback hell!

Page 31: NodeJS

Node.js as a Web server app platform

Node’s asynchronous naturemakes it an ideal platform for web server side development:● High I/O throughput● Efficient and easy management of concurrent

requests● Shares language and some tooling with the client

side● LOTS of open source libraries and modules

Page 32: NodeJS

Frameworks?

Node’s own http module is a bit low level.

We want to be able to avoid boilerplate while retaining flexibilityMany, many choices

Page 33: NodeJS

Hapi

● stable● well documented● well maintened● modular● is a good mix between flexibility and structure● good plugin ecosystem

Page 34: NodeJS

Who uses Hapi?

Page 35: NodeJS

How did it start?

Hapi short for HTTP API, or so they sayDeveloped in Walmart Labs by a guy Named Eran HammerEran Hammer also authored OAuth

Page 36: NodeJS

What does it do?

● Routes● Caching● Sessions● Logging● Authentication● Plugins

Page 37: NodeJS

Philosophy

● Configuration over code● Three Rs:

○ Reusability - plugins, handlers○ Reduce errors - strong validation, 100% test coverage○ Reflection - the applications knows it’s own structure .

this makes generating documentation easier

Page 38: NodeJS

Show me the code - routes

var Hapi = require('hapi');var server = new Hapi.Server('localhost', 8000);server.route({ method: 'GET', path: '/hello/{name}', handler: function (request, reply) { reply('hello world'); }});server.start();

Page 39: NodeJS

Config objects

The route object alse accepts a config object which controls every aspect of the request’s lifecycle such as validation, authentication, caching Its properties may depend on the plugins installed

Page 40: NodeJS

Config example

{config: {

handler: handlers.mapUsername,description: 'Get todo',notes: 'Returns a todo item by the id passed in the path',tags: ['api'],validate: {

params: {username: Joi.number()

.required()

.description('the id for the todo item'),

}} [...]

Page 41: NodeJS

Adding functionality with plugins

Almost every feature in hapi is isolated in a plugin.Even core features are registred as a plugin:● static content (inert)● validation (joi)● errors (Boom)● monitoring (Good)● … MANY more

Page 42: NodeJS

Using plugins

server.register([ Inert, Vision, { register: HapiSwagger, options: swaggerOptions }],

function (err) { server.start(function(){ }); });

Page 43: NodeJS

Writing plugins

exports.register = function (server, options, next) { server.route({ method: 'GET', path: '/test', handler: function (request, reply) { reply('test passed'); } });

next();};

Page 44: NodeJS

So everything must be a Hapi plugin?

No, of course, you can use any module as long as its framework agnostic.

Page 45: NodeJS

Most used plugins - Inert

● Download files with reply.file(path)● Can expose files or whole directoriesserver.route({ method: 'GET', path: '/{param*}', //multi segment parameter handler: { directory: { path: 'public', listing: true } }});

Page 46: NodeJS

Template rendering - Vision

var handler = function (request, reply) { reply.view('basic/index,html', {

title: getTitle() ... });

};

//basic/index.html<html> <head>

<title>{{title}}</title>..

Page 47: NodeJS

Template helpers

Providing template helpers is easy// this is the server.view config obj{

views: {helpersPath: 'helpers’ // path to the helpers dir

}};

// helpers/helper.js - only one function per file! module.exports = function(context){

// context contains the same data available to the templatereturn whatever(context.myvar);

}

Page 48: NodeJS

Template helper view

<html><head><title>Help</title></head>

<body> {{myhelper}} <!-- helper filename --></body>

</html>

Page 49: NodeJS

Validate with Joi

● Joi is a generic validation framework● It works by createing schemas and validating

objects against it● It just validates the object format it does not

peform things such as database validation● It is so powerful that documentation can be

generated from Joi schemas!

Page 50: NodeJS

Joiful example

var schema = {

username: Joi.string().alphanum().min(3).max(30).with('birthyear').required(),

birthyear: Joi.number().integer().min(1900).max(2013)};

var err = Joi.validate(data, schema, config);console.log(err ? err : 'Valid!');

Page 51: NodeJS

Hapi with Joi

server.route({

path: '/user/{id}',method: 'GET',handler: (request, reply) => {

reply(getUser(id))},config: {

validate: {params: {

id: joi.number().integer()}

}}

Page 52: NodeJS

Conditional validation

Joi.object({propertyRequired: Joi.boolean().required(),property: Joi.string().when('isGuest', {

is: true, then: Joi.required()

}),property2: Joi.string().alphanum()

}).options({ allowUnknown: true }).without('property', 'property2')

Page 53: NodeJS

Hapi, Joi and Swagger

Joi validations can be used to generate a swagger documentation pageThis is an excellent example of reflection in action

Page 54: NodeJS

Errors - Boom

Boom makes easy to generate HTTP errors Boom.unauthorized([message], [scheme], [attributes])

Boom.forbidden([message], [data])

Boom.notFound([message], [data])

Boom.methodNotAllowed([message], [data])

Boom.notAcceptable([message], [data])

Boom.proxyAuthRequired([message], [data])

Boom.clientTimeout([message], [data])

Boom.conflict([message], [data])

Page 55: NodeJS

Cookies aka server.state

server.state('session', { //cookie name path: '/', encoding: 'base64json', ttl: 10, domain: 'localhost'});

reply('success').state(

'session', //cookie name'session' //cookie value

)

Page 56: NodeJS

Authorization strategies

Strategies are provided by plugins, and can be plugged in routes:

server.auth.strategy('simple','basic',

{ validateFunc: validate });

Page 57: NodeJS

Auth validation function

function (request, username, password, callback) {

var isValid = username === user.name && password === user.password;

return callback(null, isValid, { name: user.name });

};

Page 58: NodeJS

Time to code!

sudo npm install -g makemehapi

npm install hapi

Page 59: NodeJS

Why debugging is important

● Javascript is an extremely flexibile and expressive language

● Maybe a little bit too much

● We need strong tooling support

Page 60: NodeJS

The console object

● This is our first line of defense

● Was born inside browser developer tools

● Node provides us with a preconfigured console, exposed as global

Page 61: NodeJS

stdin stderr

Page 62: NodeJS

Other console methods

● dir: explore objects● trace: print current stack trace● time/timend: basic performance profiling

Page 63: NodeJS

Static analysis

● A lot of errors can be discovered just by analyzed the source code text.

● The most two common analysis are typechecking and linting

Page 64: NodeJS

Linting

● suspiciouse code is flagged by the linter to be reviewed by the programmer

● you can configure what should be suspicious

● can also be used to enforce coding styles (useful in teams)

Page 65: NodeJS

ESLint

● Actually parses your code, instead of just analyzing text

● Pluggable

● Integrated with most code editors

Page 66: NodeJS

ESLint example config

{

"env" : {

"node" : true //this determines which globals to expect

},

"rules" : {

"quotes": [2, "double"],

"no-use-before-define": 2

}

}

Page 67: NodeJS

Logging

● An emitted stream of distinct messages from a running application

● Ordered in time

● Many applications, from debugging to performance analysis to security

Page 68: NodeJS

Structured logs

07/Mar/2004:16:06:51 -"GET request from /twiki/bin/rdiff/TWiki/NewUserTemplate?rev1=1.3&rev2=1.2 HTTP/1.1" 200 4523

vs

{“date”: “2004-04-04”, “method”: “GET”, “uri”:”/twiki/bin/rdiff/TWiki/NewUserTemplate”: header: {

/../

}}

Page 69: NodeJS

Structured loggers

Structured loggers log objects, not just strings.

We don’t have to restructure strings while analyzing data

Much easier for parsing

Page 70: NodeJS

Stack traces

It’s the record of the function calls until a certain point (usually an error).

console.log(e.stack);

Error: Something unexpected has occurred.

at main (c:\Users\Me\Documents\MyApp\app.js:9:15)

at Object. (c:\Users\Me\Documents\MyApp\app.js:17:1)

at Module._compile (module.js:460:26)

at Object.Module._extensions..js (module.js:478:10)

at Module.load (module.js:355:32)

at Function.Module._load (module.js:310:12)

at Function.Module.runMain (module.js:501:10)

at startup (node.js:129:16)

at node.js:814:3

Page 71: NodeJS

The problem with async stacktraces

setTimeout(function first() {

setTimeout(function second() {

setTimeout(function third() {

a.b.c;

}, 1);

}, 1)

}, 1)

Page 72: NodeJS

long stack traces

ReferenceError: a is not definedat third [as _onTimeout] (/home/zio/stuff/nodeschool/bugclinic/provastack.

js:4:13)at Timer.listOnTimeout (timers.js:92:15)

This is because we can see only the stack of the message currently processedby the event loop

With advanced black magic, we are eventually able to get the full stack

Page 73: NodeJS

Automated Testing

● Automated testing is incredibly cost effective

○ You get a much better understing of your code○ You get much safer code○ You are protected from regression○ Tests are the most formal kind of documentation○ You save of a LOT of time by letting the machine create

the test environment and executing the test for you○ .. this could go on for hours

Page 74: NodeJS

Runners and assertions

A test environment is usually composed by:- a test runner- an assertion library

A test is usually composed by 2+1 phase- setup- assertion- teardown (optional)

Page 75: NodeJS

Tape

We are going to use Tape- assertion and running in the same library- both very simple- outputs TAP strings

Page 76: NodeJS

Node core debugging

If for some reason you want to get node’s internal debug message it’s easy, just prepend an env variable.

#prepare to get a lot of output

NODE_DEBUG=cluster,net,http,fs,tls,module,timers nod node myapp

Page 77: NodeJS

The debug module

Yo u can use a similar approach in your code with the debug module:

var debug = require('debug')('http'), http=require('http'), name='My App';

debug('booting %s', name);

http.createServer(function(req, res){

debug(req.method + ' ' + req.url);

res.end('hello\n');

}).listen(3000, function(){

debug('listening');

});

Page 78: NodeJS

Running in debug mode

Page 79: NodeJS

Tracing vs debugging

Tracing is very specialized kind of debugging:

● It is never a functional requirement● It is meant for the developer , not the system administrator● It is commonly used for detecting bottlenecks, memory

leaks and other problem arising during continuous operations.

Page 80: NodeJS

Interactive debugging: repl

The mighty Read-Evaluate-Print-Loop

Useful to test small bits of code or playing around with libraries.

Too long to reproduce actual application in it.. wouldn’t be cool if you could expose a repl in certain part of your app?

Good news, you totally can!

Page 81: NodeJS

Replify

var replify = require('replify')

, app = require('http').createServer()

replify('realtime-101', app);

Page 82: NodeJS

The node debugger

You can start an app with the “debug” flag:node debug myapp.js

Then the app will be in debug mode and you can:- set breakpoints in code (debugger;)- navigate- execute REPLs at leisure

Page 83: NodeJS

NPM

Npm is not only a package / dependancy manager.

● It is a HUGE repository● It’s generic automation tool● A place to offer / find a job● and also a company

Page 84: NodeJS

The site

On the site you can browse packages, search them by keyword and get a good lot of metrics:● number of downloads● github statistics● even try them out! well played NPMthis is extremely important due to impressive amount of javascript packages out therehttps://www.npmjs.com/package/lodash

Page 85: NodeJS

Publishing on npm

● npm adduser● npm publish to publish the package.● Go to http://npmjs.com/package/<package>.

You can also create private modules.

Page 86: NodeJS

Versioning

The whole npm ecosystem uses semantic versioning (semver for friends). A semantic version number is composed by three integers:

MAJOR.MINOR.PATCH

Page 87: NodeJS

Semantic versioning

MAJOR is incremented when incompatible API changes are made

MINOR is incremented when backwards compatibile feature are added

PATCH is incremented when a bug is fixed

Page 88: NodeJS

Semver operators

● >, <, >=, <= ● || - OR● * - gets the most recent - dangerous● ~ update only patch - ~0.5.0 >=0.5.0 < 0.6.0● ^ upgrade only minor - ^ 0.5.0 >= 0.5.0 < 1.0.0

Page 89: NodeJS

package.json

It can be seen as the “manifest” of an applicationContains many metadata used for:● uniquely identify a package● establish authorship● lifecycle management

○ pre - post install scripts○ main file ○ ...

Page 90: NodeJS

Dissecting a package.json file

http://browsenpm.org/package.json

Page 92: NodeJS

Nodemon is a friend

(sudo) npm install -g nodemon

nodemon server.js (you will get errors)

solutions are in the master branch

Page 93: NodeJS

Troubleshooting

If you get compile errors try adding the --no-optional flag to npm install