Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Node.js for everyone

Node.js for everyone

Slides from an internal Node.js course for the Nielsen Marketing Cloud R&D developers

Ofer Itzhaki

June 08, 2017
Tweet

More Decks by Ofer Itzhaki

Other Decks in Technology

Transcript

  1. AGENDA Intro to Node.js - architecture, blocking vs. non-blocking code,

    event loop, reading files, issuing requests Events and Streams - reading, writing, piping, event emitters, event listening Modules - exporting, importing, NPM, Yarn, dependencies, semantic versioning Express - routes, middlewares, views, express servers Working with data - JSON Part 1 Testing - sinon, mocking, proxyquire, tape, coverage Processes & Clusters - child process, why cluster, process managers Best Practices - error handling, debugging, logging, monitoring, security Part 2
  2. MILESTONES 2009 - Created by Ryan Dahl, first preview of

    NPM 2010 - Express, socket.io, v0.2.0 2011 - Node.js in production at Uber & Linkedin, NPM 1.0 2012 - Node.js creator Ryan Dahl steps away from Node day-to-day, v0.8.0 2013 - The MEAN Stack, eBay’s First Node.js Application, Node.js Memory Leak at Walmart 2014 - Node.js Advisory Board, IO.js – Evented I/O for V8 Javascript 2015 - IO.js 1.0.0, Node.js Foundation(Joyent, IBM, Microsoft, PayPal, Fidelity, SAP and The Linux Foundation), Node.js and io.js are merging, v4.0 is the new v1.0 2016 - v6.0: 93% support in ES2015 2017 - v7.x: 97% support in ES2015 including async/await
  3. "A PLATFORM BUILT ON CHROME’S JAVASCRIPT RUNTIME FOR EASILY BUILDING

    FAST, SCALABLE NETWORK APPLICATIONS." What is Node?
  4. “USES AN EVENT-DRIVEN, NON- BLOCKING I/O MODEL THAT MAKES IT

    LIGHTWEIGHT AND EFFICIENT.” What is Node?
  5. BLOCKING VS. NON BLOCKING IO const getUserSync = require('./get-user-sync') const

    user1 = getUserSync(1) console.log('user1', user1) const user2 = getUserSync(2) console.log('user2', user2) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 const getUser = require('./get-user') getUser(1, (user1) => { console.log('user1', user1) }) getUser(2, (user2) => { console.log('user2', user2) }) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 blocking non-blocking
  6. BLOCKING VS. NON BLOCKING IO const getUserSync = require('./get-user-sync') const

    user1 = getUserSync(1) console.log('user1', user1) const user2 = getUserSync(2) console.log('user2', user2) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 waiting on user1 const getUser = require('./get-user') getUser(1, (user1) => { console.log('user1', user1) }) getUser(2, (user2) => { console.log('user2', user2) }) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 blocking non-blocking
  7. BLOCKING VS. NON BLOCKING IO const getUserSync = require('./get-user-sync') const

    user1 = getUserSync(1) console.log('user1', user1) const user2 = getUserSync(2) console.log('user2', user2) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 waiting on user1 printing user1 const getUser = require('./get-user') getUser(1, (user1) => { console.log('user1', user1) }) getUser(2, (user2) => { console.log('user2', user2) }) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 blocking non-blocking
  8. BLOCKING VS. NON BLOCKING IO const getUserSync = require('./get-user-sync') const

    user1 = getUserSync(1) console.log('user1', user1) const user2 = getUserSync(2) console.log('user2', user2) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 waiting on user1 printing user1 waiting on user2 const getUser = require('./get-user') getUser(1, (user1) => { console.log('user1', user1) }) getUser(2, (user2) => { console.log('user2', user2) }) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 blocking non-blocking
  9. BLOCKING VS. NON BLOCKING IO const getUserSync = require('./get-user-sync') const

    user1 = getUserSync(1) console.log('user1', user1) const user2 = getUserSync(2) console.log('user2', user2) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 waiting on user1 printing user1 waiting on user2 printing user2 const getUser = require('./get-user') getUser(1, (user1) => { console.log('user1', user1) }) getUser(2, (user2) => { console.log('user2', user2) }) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 blocking non-blocking
  10. BLOCKING VS. NON BLOCKING IO const getUserSync = require('./get-user-sync') const

    user1 = getUserSync(1) console.log('user1', user1) const user2 = getUserSync(2) console.log('user2', user2) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 waiting on user1 printing user1 waiting on user2 printing user2 printing sum const getUser = require('./get-user') getUser(1, (user1) => { console.log('user1', user1) }) getUser(2, (user2) => { console.log('user2', user2) }) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 blocking non-blocking
  11. BLOCKING VS. NON BLOCKING IO const getUserSync = require('./get-user-sync') const

    user1 = getUserSync(1) console.log('user1', user1) const user2 = getUserSync(2) console.log('user2', user2) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 waiting on user1 printing user1 waiting on user2 printing user2 printing sum const getUser = require('./get-user') getUser(1, (user1) => { console.log('user1', user1) }) getUser(2, (user2) => { console.log('user2', user2) }) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 starting getUser for user1 blocking non-blocking
  12. BLOCKING VS. NON BLOCKING IO const getUserSync = require('./get-user-sync') const

    user1 = getUserSync(1) console.log('user1', user1) const user2 = getUserSync(2) console.log('user2', user2) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 waiting on user1 printing user1 waiting on user2 printing user2 printing sum const getUser = require('./get-user') getUser(1, (user1) => { console.log('user1', user1) }) getUser(2, (user2) => { console.log('user2', user2) }) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 starting getUser for user1 blocking non-blocking starting getUser for user2
  13. BLOCKING VS. NON BLOCKING IO const getUserSync = require('./get-user-sync') const

    user1 = getUserSync(1) console.log('user1', user1) const user2 = getUserSync(2) console.log('user2', user2) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 waiting on user1 printing user1 waiting on user2 printing user2 printing sum const getUser = require('./get-user') getUser(1, (user1) => { console.log('user1', user1) }) getUser(2, (user2) => { console.log('user2', user2) }) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 starting getUser for user1 printing sum blocking non-blocking starting getUser for user2
  14. BLOCKING VS. NON BLOCKING IO const getUserSync = require('./get-user-sync') const

    user1 = getUserSync(1) console.log('user1', user1) const user2 = getUserSync(2) console.log('user2', user2) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 waiting on user1 printing user1 waiting on user2 printing user2 printing sum const getUser = require('./get-user') getUser(1, (user1) => { console.log('user1', user1) }) getUser(2, (user2) => { console.log('user2', user2) }) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 starting getUser for user1 printing sum blocking non-blocking starting getUser for user2 printing user1
  15. BLOCKING VS. NON BLOCKING IO const getUserSync = require('./get-user-sync') const

    user1 = getUserSync(1) console.log('user1', user1) const user2 = getUserSync(2) console.log('user2', user2) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 waiting on user1 printing user1 waiting on user2 printing user2 printing sum const getUser = require('./get-user') getUser(1, (user1) => { console.log('user1', user1) }) getUser(2, (user2) => { console.log('user2', user2) }) const sum = 1 + 1 console.log(`The sum is ${sum}`) 1 2 3 4 5 6 7 starting getUser for user1 printing sum blocking non-blocking starting getUser for user2 printing user1 printing user2
  16. V8 JS engine built by Google Open source Written in

    C++ Client (Google Chrome) & Server (Node.js) Compiles JS to machine code Has two compilers JS Code JIT Compiler Inline caches Optimisation compiler Machine Code
  17. EVENT LOOP Event Queue Event Loop Worker Threads Register Callback

    Operation Complete Trigger Callback File System Network Processes HTTP Request Read File (Single Thread) Read Stream
  18. EVENTS Object (emitter) function (listener) Many objects in Node emit

    events event callback net.Server request EventEmitter fs.readStream data EventEmitter
  19. EVENTS - BASIC EXAMPLE “someone read this file!” “I’m reading…”

    “I’m done reading, someone print it!” emitter.emit('startRead','/etc/hosts') emitter.on('startRead', (file) => {...} emitter.emit('printContent', data) emitter.on('printContent', (data) => {...} // require the EventEmitter from the events module const EventEmitter = require('events').EventEmitter const fs = require('fs') // create an instance of the EventEmitter object const emitter = new EventEmitter() emitter.on('startRead', (file) => { console.log('Started Reading file...\n') fs.readFile(file, 'utf8', (err, data) => { if (err) { emitter.emit('error', 'from_read') } else{ console.log('Done Reading file...\n') emitter.emit('printContent', data) } }) }) emitter.on('printContent', (data) => { console.log('Printing content of file...\n') console.log(data) emitter.emit('done') }) emitter.on('error', (type) => { console.log(`Faced error while ${type}`) emitter.emit('done') }) emitter.on('done', () => { console.log('Ok its done !') }) emitter.emit('startRead', '/etc/hosts')
  20. EVENTS - BASIC EXAMPLE “someone read this file!” “I’m reading…”

    “I’m done reading, someone print it!” emitter.emit('startRead','/etc/hosts') emitter.on('startRead', (file) => {...} emitter.emit('printContent', data) emitter.on('printContent', (data) => {...} // require the EventEmitter from the events module const EventEmitter = require('events').EventEmitter const fs = require('fs') // create an instance of the EventEmitter object const emitter = new EventEmitter() emitter.on('startRead', (file) => { console.log('Started Reading file...\n') fs.readFile(file, 'utf8', (err, data) => { if (err) { emitter.emit('error', 'from_read') } else{ console.log('Done Reading file...\n') emitter.emit('printContent', data) } }) }) emitter.on('printContent', (data) => { console.log('Printing content of file...\n') console.log(data) emitter.emit('done') }) emitter.on('error', (type) => { console.log(`Faced error while ${type}`) emitter.emit('done') }) emitter.on('done', () => { console.log('Ok its done !') }) emitter.emit('startRead', '/etc/hosts')
  21. EVENTS - BASIC EXAMPLE “someone read this file!” “I’m reading…”

    “I’m done reading, someone print it!” emitter.emit('startRead','/etc/hosts') emitter.on('startRead', (file) => {...} emitter.emit('printContent', data) emitter.on('printContent', (data) => {...} // require the EventEmitter from the events module const EventEmitter = require('events').EventEmitter const fs = require('fs') // create an instance of the EventEmitter object const emitter = new EventEmitter() emitter.on('startRead', (file) => { console.log('Started Reading file...\n') fs.readFile(file, 'utf8', (err, data) => { if (err) { emitter.emit('error', 'from_read') } else{ console.log('Done Reading file...\n') emitter.emit('printContent', data) } }) }) emitter.on('printContent', (data) => { console.log('Printing content of file...\n') console.log(data) emitter.emit('done') }) emitter.on('error', (type) => { console.log(`Faced error while ${type}`) emitter.emit('done') }) emitter.on('done', () => { console.log('Ok its done !') }) emitter.emit('startRead', '/etc/hosts')
  22. EVENTS - BASIC EXAMPLE “someone read this file!” “I’m reading…”

    “I’m done reading, someone print it!” emitter.emit('startRead','/etc/hosts') emitter.on('startRead', (file) => {...} emitter.emit('printContent', data) emitter.on('printContent', (data) => {...} // require the EventEmitter from the events module const EventEmitter = require('events').EventEmitter const fs = require('fs') // create an instance of the EventEmitter object const emitter = new EventEmitter() emitter.on('startRead', (file) => { console.log('Started Reading file...\n') fs.readFile(file, 'utf8', (err, data) => { if (err) { emitter.emit('error', 'from_read') } else{ console.log('Done Reading file...\n') emitter.emit('printContent', data) } }) }) emitter.on('printContent', (data) => { console.log('Printing content of file...\n') console.log(data) emitter.emit('done') }) emitter.on('error', (type) => { console.log(`Faced error while ${type}`) emitter.emit('done') }) emitter.on('done', () => { console.log('Ok its done !') }) emitter.emit('startRead', '/etc/hosts')
  23. EVENTS - BASIC EXAMPLE “someone read this file!” “I’m reading…”

    “I’m done reading, someone print it!” emitter.emit('startRead','/etc/hosts') emitter.on('startRead', (file) => {...} emitter.emit('printContent', data) emitter.on('printContent', (data) => {...} // require the EventEmitter from the events module const EventEmitter = require('events').EventEmitter const fs = require('fs') // create an instance of the EventEmitter object const emitter = new EventEmitter() emitter.on('startRead', (file) => { console.log('Started Reading file...\n') fs.readFile(file, 'utf8', (err, data) => { if (err) { emitter.emit('error', 'from_read') } else{ console.log('Done Reading file...\n') emitter.emit('printContent', data) } }) }) emitter.on('printContent', (data) => { console.log('Printing content of file...\n') console.log(data) emitter.emit('done') }) emitter.on('error', (type) => { console.log(`Faced error while ${type}`) emitter.emit('done') }) emitter.on('done', () => { console.log('Ok its done !') }) emitter.emit('startRead', '/etc/hosts')
  24. EVENTS - BASIC EXAMPLE “someone read this file!” “I’m reading…”

    “I’m done reading, someone print it!” emitter.emit('startRead','/etc/hosts') emitter.on('startRead', (file) => {...} emitter.emit('printContent', data) emitter.on('printContent', (data) => {...} // require the EventEmitter from the events module const EventEmitter = require('events').EventEmitter const fs = require('fs') // create an instance of the EventEmitter object const emitter = new EventEmitter() emitter.on('startRead', (file) => { console.log('Started Reading file...\n') fs.readFile(file, 'utf8', (err, data) => { if (err) { emitter.emit('error', 'from_read') } else{ console.log('Done Reading file...\n') emitter.emit('printContent', data) } }) }) emitter.on('printContent', (data) => { console.log('Printing content of file...\n') console.log(data) emitter.emit('done') }) emitter.on('error', (type) => { console.log(`Faced error while ${type}`) emitter.emit('done') }) emitter.on('done', () => { console.log('Ok its done !') }) emitter.emit('startRead', '/etc/hosts')
  25. EVENTS - BASIC EXAMPLE “someone read this file!” “I’m reading…”

    “I’m done reading, someone print it!” emitter.emit('startRead','/etc/hosts') emitter.on('startRead', (file) => {...} emitter.emit('printContent', data) emitter.on('printContent', (data) => {...} // require the EventEmitter from the events module const EventEmitter = require('events').EventEmitter const fs = require('fs') // create an instance of the EventEmitter object const emitter = new EventEmitter() emitter.on('startRead', (file) => { console.log('Started Reading file...\n') fs.readFile(file, 'utf8', (err, data) => { if (err) { emitter.emit('error', 'from_read') } else{ console.log('Done Reading file...\n') emitter.emit('printContent', data) } }) }) emitter.on('printContent', (data) => { console.log('Printing content of file...\n') console.log(data) emitter.emit('done') }) emitter.on('error', (type) => { console.log(`Faced error while ${type}`) emitter.emit('done') }) emitter.on('done', () => { console.log('Ok its done !') }) emitter.emit('startRead', '/etc/hosts')
  26. EVENTS - EXTENDING EVENT EMITTER const EventEmitter = require('events') class

    RickAndMorty extends EventEmitter { constructor () { super() this.id = 0 this.episodes = [] } save (obj) { obj.id = this.id++ this.episodes.push(obj) this.emit('savedEpisode', obj) } } const rickAndMorty = new RickAndMorty() rickAndMorty.on('savedEpisode', (episode) => { console.log(`saved: ${episode.name} (${episode.code})`) }) rickAndMorty.save({ code: 's01e07', name: 'Raising Gazorpazorp' }) rickAndMorty.save({ code: 's02e06', name: 'The Ricks Must Be Crazy' })
  27. EVENTS - EXTENDING EVENT EMITTER const EventEmitter = require('events') class

    RickAndMorty extends EventEmitter { constructor () { super() this.id = 0 this.episodes = [] } save (obj) { obj.id = this.id++ this.episodes.push(obj) this.emit('savedEpisode', obj) } } const rickAndMorty = new RickAndMorty() rickAndMorty.on('savedEpisode', (episode) => { console.log(`saved: ${episode.name} (${episode.code})`) }) rickAndMorty.save({ code: 's01e07', name: 'Raising Gazorpazorp' }) rickAndMorty.save({ code: 's02e06', name: 'The Ricks Must Be Crazy' })
  28. EVENTS - EXTENDING EVENT EMITTER const EventEmitter = require('events') class

    RickAndMorty extends EventEmitter { constructor () { super() this.id = 0 this.episodes = [] } save (obj) { obj.id = this.id++ this.episodes.push(obj) this.emit('savedEpisode', obj) } } const rickAndMorty = new RickAndMorty() rickAndMorty.on('savedEpisode', (episode) => { console.log(`saved: ${episode.name} (${episode.code})`) }) rickAndMorty.save({ code: 's01e07', name: 'Raising Gazorpazorp' }) rickAndMorty.save({ code: 's02e06', name: 'The Ricks Must Be Crazy' })
  29. EVENTS - EXTENDING EVENT EMITTER const EventEmitter = require('events') class

    RickAndMorty extends EventEmitter { constructor () { super() this.id = 0 this.episodes = [] } save (obj) { obj.id = this.id++ this.episodes.push(obj) this.emit('savedEpisode', obj) } } const rickAndMorty = new RickAndMorty() rickAndMorty.on('savedEpisode', (episode) => { console.log(`saved: ${episode.name} (${episode.code})`) }) rickAndMorty.save({ code: 's01e07', name: 'Raising Gazorpazorp' }) rickAndMorty.save({ code: 's02e06', name: 'The Ricks Must Be Crazy' })
  30. EVENTS - EXTENDING EVENT EMITTER const EventEmitter = require('events') class

    RickAndMorty extends EventEmitter { constructor () { super() this.id = 0 this.episodes = [] } save (obj) { obj.id = this.id++ this.episodes.push(obj) this.emit('savedEpisode', obj) } } const rickAndMorty = new RickAndMorty() rickAndMorty.on('savedEpisode', (episode) => { console.log(`saved: ${episode.name} (${episode.code})`) }) rickAndMorty.save({ code: 's01e07', name: 'Raising Gazorpazorp' }) rickAndMorty.save({ code: 's02e06', name: 'The Ricks Must Be Crazy' })
  31. EVENTS - API Listen once Multiple listeners on the same

    event Set/Get max listeners Prepend listeners Count listeners Get all listeners event names Error event - best practice, always assign listener for `error` event https://nodejs.org/api/events.html
  32. STREAMS source destination A way to read and write data

    in pieces (chunks) buffer readable HTTP request(server) HTTP response(client) fs.createReadStream(src file) process.stdin
  33. STREAMS source destination A way to read and write data

    in pieces (chunks) buffer readable HTTP request(server) HTTP response(client) fs.createReadStream(src file) process.stdin writable HTTP request(client) HTTP response(server) fs.createWriteStream(dest file) process.stdout
  34. STREAMS source destination A way to read and write data

    in pieces (chunks) buffer readable HTTP request(server) HTTP response(client) fs.createReadStream(src file) process.stdin writable HTTP request(client) HTTP response(server) fs.createWriteStream(dest file) process.stdout duplex and transform encoding/decoding(crypto) compress/decompress(zlib) filtering data transforming data net.Socket read write your code external duplex transform your code write transform read or read transform write
  35. STREAMS - PIPE A function that takes a readable stream(source)

    and hooks the output to a writable stream(destination) source.pipe(destination)
  36. STREAMS - PIPE A function that takes a readable stream(source)

    and hooks the output to a writable stream(destination) source.pipe(destination) .pipe(destination) returns destination so we can chain multiple .pipe calls together
  37. STREAMS - PIPE A function that takes a readable stream(source)

    and hooks the output to a writable stream(destination) source.pipe(destination) .pipe(destination) returns destination so we can chain multiple .pipe calls together a.pipe(b).pipe(c).pipe(d)
  38. STREAMS - PIPE A function that takes a readable stream(source)

    and hooks the output to a writable stream(destination) source.pipe(destination) .pipe(destination) returns destination so we can chain multiple .pipe calls together a.pipe(b).pipe(c).pipe(d) kinda like on the commend line
  39. STREAMS - PIPE A function that takes a readable stream(source)

    and hooks the output to a writable stream(destination) source.pipe(destination) .pipe(destination) returns destination so we can chain multiple .pipe calls together a.pipe(b).pipe(c).pipe(d) kinda like on the commend line a | b | c | d
  40. STREAMS - PIPE A function that takes a readable stream(source)

    and hooks the output to a writable stream(destination) source.pipe(destination) .pipe(destination) returns destination so we can chain multiple .pipe calls together a.pipe(b).pipe(c).pipe(d) kinda like on the commend line a | b | c | d const fs = require('fs') const zlib = require('zlib') const r = fs.createReadStream('data.csv') const z = zlib.createGzip() const w = fs.createWriteStream('data.csv.gz') r.pipe(z).pipe(w)
  41. STREAMS - WHY YOU SHOULD USE THEM const http =

    require('http') const fs = require('fs') const server = http.createServer((req, res) => { fs.readFile(__dirname + '/data.csv', (err, data) => { res.end(data) }) }) server.listen(4433)
  42. STREAMS - WHY YOU SHOULD USE THEM const http =

    require('http') const fs = require('fs') const server = http.createServer((req, res) => { fs.readFile(__dirname + '/data.csv', (err, data) => { res.end(data) }) }) server.listen(4433) buffers up the entire file into memory before writing back the result to clients 1. high memory usage 2. bad user experience
  43. STREAMS - WHY YOU SHOULD USE THEM const http =

    require('http') const fs = require('fs') const server = http.createServer((req, res) => { fs.readFile(__dirname + '/data.csv', (err, data) => { res.end(data) }) }) server.listen(4433) buffers up the entire file into memory before writing back the result to clients 1. high memory usage 2. bad user experience const server = http.createServer((req, res) => { const stream = fs.createReadStream(__dirname + '/data.csv') stream.pipe(res) }) better
  44. STREAMS - WHY YOU SHOULD USE THEM const http =

    require('http') const fs = require('fs') const server = http.createServer((req, res) => { fs.readFile(__dirname + '/data.csv', (err, data) => { res.end(data) }) }) server.listen(4433) buffers up the entire file into memory before writing back the result to clients 1. high memory usage 2. bad user experience const server = http.createServer((req, res) => { const stream = fs.createReadStream(__dirname + '/data.csv') stream.pipe(res) }) better with compression const zlib = require('zlib') const server = http.createServer((req, res) => { const gzip = zlib.createGzip() fs.createReadStream(__dirname + '/data.csv') .pipe(gzip) .pipe(res) })
  45. STREAMS - EXAMPLE const fs = require('fs') const Transform =

    require('stream').Transform const read = fs.createReadStream('characters.txt', 'utf8') const write = fs.createWriteStream('favorite.txt') read.on('data', (data) => { console.log(data) }) read.pipe(process.stdout) class FavoriteChars extends Transform { constructor (options) { super(options) } _transform (chunk, enc, done) { chunk = chunk .toString() .split('\n') .filter(chr => ['Rick', 'Morty'].includes(chr)) .join('\n') this.push(chunk) done() } } read.pipe(new FavoriteChars()).pipe(write)
  46. STREAMS - EXAMPLE const fs = require('fs') const Transform =

    require('stream').Transform const read = fs.createReadStream('characters.txt', 'utf8') const write = fs.createWriteStream('favorite.txt') read.on('data', (data) => { console.log(data) }) read.pipe(process.stdout) class FavoriteChars extends Transform { constructor (options) { super(options) } _transform (chunk, enc, done) { chunk = chunk .toString() .split('\n') .filter(chr => ['Rick', 'Morty'].includes(chr)) .join('\n') this.push(chunk) done() } } read.pipe(new FavoriteChars()).pipe(write)
  47. STREAMS - EXAMPLE const fs = require('fs') const Transform =

    require('stream').Transform const read = fs.createReadStream('characters.txt', 'utf8') const write = fs.createWriteStream('favorite.txt') read.on('data', (data) => { console.log(data) }) read.pipe(process.stdout) class FavoriteChars extends Transform { constructor (options) { super(options) } _transform (chunk, enc, done) { chunk = chunk .toString() .split('\n') .filter(chr => ['Rick', 'Morty'].includes(chr)) .join('\n') this.push(chunk) done() } } read.pipe(new FavoriteChars()).pipe(write)
  48. STREAMS - EXAMPLE const fs = require('fs') const Transform =

    require('stream').Transform const read = fs.createReadStream('characters.txt', 'utf8') const write = fs.createWriteStream('favorite.txt') read.on('data', (data) => { console.log(data) }) read.pipe(process.stdout) class FavoriteChars extends Transform { constructor (options) { super(options) } _transform (chunk, enc, done) { chunk = chunk .toString() .split('\n') .filter(chr => ['Rick', 'Morty'].includes(chr)) .join('\n') this.push(chunk) done() } } read.pipe(new FavoriteChars()).pipe(write)
  49. STREAMS - EXAMPLE const fs = require('fs') const Transform =

    require('stream').Transform const read = fs.createReadStream('characters.txt', 'utf8') const write = fs.createWriteStream('favorite.txt') read.on('data', (data) => { console.log(data) }) read.pipe(process.stdout) class FavoriteChars extends Transform { constructor (options) { super(options) } _transform (chunk, enc, done) { chunk = chunk .toString() .split('\n') .filter(chr => ['Rick', 'Morty'].includes(chr)) .join('\n') this.push(chunk) done() } } read.pipe(new FavoriteChars()).pipe(write)
  50. STREAMS - EXAMPLE const fs = require('fs') const Transform =

    require('stream').Transform const read = fs.createReadStream('characters.txt', 'utf8') const write = fs.createWriteStream('favorite.txt') read.on('data', (data) => { console.log(data) }) read.pipe(process.stdout) class FavoriteChars extends Transform { constructor (options) { super(options) } _transform (chunk, enc, done) { chunk = chunk .toString() .split('\n') .filter(chr => ['Rick', 'Morty'].includes(chr)) .join('\n') this.push(chunk) done() } } read.pipe(new FavoriteChars()).pipe(write)
  51. STREAMS - EXAMPLE const fs = require('fs') const Transform =

    require('stream').Transform const read = fs.createReadStream('characters.txt', 'utf8') const write = fs.createWriteStream('favorite.txt') read.on('data', (data) => { console.log(data) }) read.pipe(process.stdout) class FavoriteChars extends Transform { constructor (options) { super(options) } _transform (chunk, enc, done) { chunk = chunk .toString() .split('\n') .filter(chr => ['Rick', 'Morty'].includes(chr)) .join('\n') this.push(chunk) done() } } read.pipe(new FavoriteChars()).pipe(write)
  52. STREAMS - EXAMPLE const fs = require('fs') const Transform =

    require('stream').Transform const read = fs.createReadStream('characters.txt', 'utf8') const write = fs.createWriteStream('favorite.txt') read.on('data', (data) => { console.log(data) }) read.pipe(process.stdout) class FavoriteChars extends Transform { constructor (options) { super(options) } _transform (chunk, enc, done) { chunk = chunk .toString() .split('\n') .filter(chr => ['Rick', 'Morty'].includes(chr)) .join('\n') this.push(chunk) done() } } read.pipe(new FavoriteChars()).pipe(write)
  53. MODULES Module: A reusable block of code whose existence does

    not accidentally impact other code CommonJS: An agreed upon standard for how code modules should be structured rick.js morty.js const callRick = () => { console.log('Wubba-lubba-dub-dub!') } module.exports = callRick const callRick = require('./rick') callRick()
  54. MODULES Module: A reusable block of code whose existence does

    not accidentally impact other code CommonJS: An agreed upon standard for how code modules should be structured rick.js morty.js const callRick = () => { console.log('Wubba-lubba-dub-dub!') } module.exports = callRick const callRick = require('./rick') callRick() ?
  55. (function (exports, require, module, __filename, __dirname) { }); MODULES const

    callRick = () => { console.log('Wubba-lubba-dub-dub!') } module.exports = callRick
  56. (function (exports, require, module, __filename, __dirname) { }); MODULES const

    callRick = () => { console.log('Wubba-lubba-dub-dub!') } module.exports = callRick fn(module.exports, require, module, filename, dirname)
  57. (function (exports, require, module, __filename, __dirname) { }); MODULES const

    callRick = () => { console.log('Wubba-lubba-dub-dub!') } module.exports = callRick fn(module.exports, require, module, filename, dirname) return module.exports this is what require returns
  58. MODULES - PATTERNS // 0. export all things! module.exports =

    1 module.exports = 'R&M' module.exports = {name: 'Rick'} module.exports = ['Rick', 'Morty'] module.exports = new Date() // 1. override module.exports object with function expression module.exports = () => { console.log('Wubba-lubba-dub-dub!') } // 2. assign function expression as method of exports module.exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } class Rick { constructor () { this.greet = 'Wubba-lubba-dub-dub!' } callRick () { console.log(this.greet) } } // 3. export new class(function) instance module.exports = new Rick() // 4. export class(function) itself module.exports = Rick // 5. export multiple modules in single export const Morty = { callMorty: () => console.log('Oh Geez!') } module.exports = { Rick, Morty } // 0. console.log(require('./rickAndMorty')) // 1 console.log(require('./rickAndMorty')) // 'R&M' console.log(require('./rickAndMorty')) // {name: 'Rick'} console.log(require('./rickAndMorty')) // ['Rick', 'Morty'] console.log(require('./rickAndMorty')).now() // 1495441119790 // 1. const callRick = require('./callRick') callRick() // 2. const callRick = require('./callRick').callRick callRick() // 3. const Rick = require('./rick') Rick.greet = 'shum-shum-schlippety-dop!' Rick.callRick() const Rick = require('./rick') Rick.callRick() // 4. const Rick = require('./rick') const rick = new Rick() rick.callRick() // 5. const rickAndMorty = require('./rickAndMorty') const morty = rickAndMorty.Morty morty.callMorty() const rick = new rickAndMorty.Rick() rick.callRick()
  59. MODULES - PATTERNS // 0. export all things! module.exports =

    1 module.exports = 'R&M' module.exports = {name: 'Rick'} module.exports = ['Rick', 'Morty'] module.exports = new Date() // 1. override module.exports object with function expression module.exports = () => { console.log('Wubba-lubba-dub-dub!') } // 2. assign function expression as method of exports module.exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } class Rick { constructor () { this.greet = 'Wubba-lubba-dub-dub!' } callRick () { console.log(this.greet) } } // 3. export new class(function) instance module.exports = new Rick() // 4. export class(function) itself module.exports = Rick // 5. export multiple modules in single export const Morty = { callMorty: () => console.log('Oh Geez!') } module.exports = { Rick, Morty } // 0. console.log(require('./rickAndMorty')) // 1 console.log(require('./rickAndMorty')) // 'R&M' console.log(require('./rickAndMorty')) // {name: 'Rick'} console.log(require('./rickAndMorty')) // ['Rick', 'Morty'] console.log(require('./rickAndMorty')).now() // 1495441119790 // 1. const callRick = require('./callRick') callRick() // 2. const callRick = require('./callRick').callRick callRick() // 3. const Rick = require('./rick') Rick.greet = 'shum-shum-schlippety-dop!' Rick.callRick() const Rick = require('./rick') Rick.callRick() // 4. const Rick = require('./rick') const rick = new Rick() rick.callRick() // 5. const rickAndMorty = require('./rickAndMorty') const morty = rickAndMorty.Morty morty.callMorty() const rick = new rickAndMorty.Rick() rick.callRick()
  60. MODULES - PATTERNS // 0. export all things! module.exports =

    1 module.exports = 'R&M' module.exports = {name: 'Rick'} module.exports = ['Rick', 'Morty'] module.exports = new Date() // 1. override module.exports object with function expression module.exports = () => { console.log('Wubba-lubba-dub-dub!') } // 2. assign function expression as method of exports module.exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } class Rick { constructor () { this.greet = 'Wubba-lubba-dub-dub!' } callRick () { console.log(this.greet) } } // 3. export new class(function) instance module.exports = new Rick() // 4. export class(function) itself module.exports = Rick // 5. export multiple modules in single export const Morty = { callMorty: () => console.log('Oh Geez!') } module.exports = { Rick, Morty } // 0. console.log(require('./rickAndMorty')) // 1 console.log(require('./rickAndMorty')) // 'R&M' console.log(require('./rickAndMorty')) // {name: 'Rick'} console.log(require('./rickAndMorty')) // ['Rick', 'Morty'] console.log(require('./rickAndMorty')).now() // 1495441119790 // 1. const callRick = require('./callRick') callRick() // 2. const callRick = require('./callRick').callRick callRick() // 3. const Rick = require('./rick') Rick.greet = 'shum-shum-schlippety-dop!' Rick.callRick() const Rick = require('./rick') Rick.callRick() // 4. const Rick = require('./rick') const rick = new Rick() rick.callRick() // 5. const rickAndMorty = require('./rickAndMorty') const morty = rickAndMorty.Morty morty.callMorty() const rick = new rickAndMorty.Rick() rick.callRick()
  61. MODULES - PATTERNS // 0. export all things! module.exports =

    1 module.exports = 'R&M' module.exports = {name: 'Rick'} module.exports = ['Rick', 'Morty'] module.exports = new Date() // 1. override module.exports object with function expression module.exports = () => { console.log('Wubba-lubba-dub-dub!') } // 2. assign function expression as method of exports module.exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } class Rick { constructor () { this.greet = 'Wubba-lubba-dub-dub!' } callRick () { console.log(this.greet) } } // 3. export new class(function) instance module.exports = new Rick() // 4. export class(function) itself module.exports = Rick // 5. export multiple modules in single export const Morty = { callMorty: () => console.log('Oh Geez!') } module.exports = { Rick, Morty } // 0. console.log(require('./rickAndMorty')) // 1 console.log(require('./rickAndMorty')) // 'R&M' console.log(require('./rickAndMorty')) // {name: 'Rick'} console.log(require('./rickAndMorty')) // ['Rick', 'Morty'] console.log(require('./rickAndMorty')).now() // 1495441119790 // 1. const callRick = require('./callRick') callRick() // 2. const callRick = require('./callRick').callRick callRick() // 3. const Rick = require('./rick') Rick.greet = 'shum-shum-schlippety-dop!' Rick.callRick() const Rick = require('./rick') Rick.callRick() // 4. const Rick = require('./rick') const rick = new Rick() rick.callRick() // 5. const rickAndMorty = require('./rickAndMorty') const morty = rickAndMorty.Morty morty.callMorty() const rick = new rickAndMorty.Rick() rick.callRick()
  62. MODULES - PATTERNS // 0. export all things! module.exports =

    1 module.exports = 'R&M' module.exports = {name: 'Rick'} module.exports = ['Rick', 'Morty'] module.exports = new Date() // 1. override module.exports object with function expression module.exports = () => { console.log('Wubba-lubba-dub-dub!') } // 2. assign function expression as method of exports module.exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } class Rick { constructor () { this.greet = 'Wubba-lubba-dub-dub!' } callRick () { console.log(this.greet) } } // 3. export new class(function) instance module.exports = new Rick() // 4. export class(function) itself module.exports = Rick // 5. export multiple modules in single export const Morty = { callMorty: () => console.log('Oh Geez!') } module.exports = { Rick, Morty } // 0. console.log(require('./rickAndMorty')) // 1 console.log(require('./rickAndMorty')) // 'R&M' console.log(require('./rickAndMorty')) // {name: 'Rick'} console.log(require('./rickAndMorty')) // ['Rick', 'Morty'] console.log(require('./rickAndMorty')).now() // 1495441119790 // 1. const callRick = require('./callRick') callRick() // 2. const callRick = require('./callRick').callRick callRick() // 3. const Rick = require('./rick') Rick.greet = 'shum-shum-schlippety-dop!' Rick.callRick() const Rick = require('./rick') Rick.callRick() // 4. const Rick = require('./rick') const rick = new Rick() rick.callRick() // 5. const rickAndMorty = require('./rickAndMorty') const morty = rickAndMorty.Morty morty.callMorty() const rick = new rickAndMorty.Rick() rick.callRick()
  63. MODULES - PATTERNS // 0. export all things! module.exports =

    1 module.exports = 'R&M' module.exports = {name: 'Rick'} module.exports = ['Rick', 'Morty'] module.exports = new Date() // 1. override module.exports object with function expression module.exports = () => { console.log('Wubba-lubba-dub-dub!') } // 2. assign function expression as method of exports module.exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } class Rick { constructor () { this.greet = 'Wubba-lubba-dub-dub!' } callRick () { console.log(this.greet) } } // 3. export new class(function) instance module.exports = new Rick() // 4. export class(function) itself module.exports = Rick // 5. export multiple modules in single export const Morty = { callMorty: () => console.log('Oh Geez!') } module.exports = { Rick, Morty } // 0. console.log(require('./rickAndMorty')) // 1 console.log(require('./rickAndMorty')) // 'R&M' console.log(require('./rickAndMorty')) // {name: 'Rick'} console.log(require('./rickAndMorty')) // ['Rick', 'Morty'] console.log(require('./rickAndMorty')).now() // 1495441119790 // 1. const callRick = require('./callRick') callRick() // 2. const callRick = require('./callRick').callRick callRick() // 3. const Rick = require('./rick') Rick.greet = 'shum-shum-schlippety-dop!' Rick.callRick() const Rick = require('./rick') Rick.callRick() // 4. const Rick = require('./rick') const rick = new Rick() rick.callRick() // 5. const rickAndMorty = require('./rickAndMorty') const morty = rickAndMorty.Morty morty.callMorty() const rick = new rickAndMorty.Rick() rick.callRick()
  64. MODULES - PATTERNS // 0. export all things! module.exports =

    1 module.exports = 'R&M' module.exports = {name: 'Rick'} module.exports = ['Rick', 'Morty'] module.exports = new Date() // 1. override module.exports object with function expression module.exports = () => { console.log('Wubba-lubba-dub-dub!') } // 2. assign function expression as method of exports module.exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } class Rick { constructor () { this.greet = 'Wubba-lubba-dub-dub!' } callRick () { console.log(this.greet) } } // 3. export new class(function) instance module.exports = new Rick() // 4. export class(function) itself module.exports = Rick // 5. export multiple modules in single export const Morty = { callMorty: () => console.log('Oh Geez!') } module.exports = { Rick, Morty } // 0. console.log(require('./rickAndMorty')) // 1 console.log(require('./rickAndMorty')) // 'R&M' console.log(require('./rickAndMorty')) // {name: 'Rick'} console.log(require('./rickAndMorty')) // ['Rick', 'Morty'] console.log(require('./rickAndMorty')).now() // 1495441119790 // 1. const callRick = require('./callRick') callRick() // 2. const callRick = require('./callRick').callRick callRick() // 3. const Rick = require('./rick') Rick.greet = 'shum-shum-schlippety-dop!' Rick.callRick() const Rick = require('./rick') Rick.callRick() // 4. const Rick = require('./rick') const rick = new Rick() rick.callRick() // 5. const rickAndMorty = require('./rickAndMorty') const morty = rickAndMorty.Morty morty.callMorty() const rick = new rickAndMorty.Rick() rick.callRick()
  65. MODULES - PATTERNS // 0. export all things! module.exports =

    1 module.exports = 'R&M' module.exports = {name: 'Rick'} module.exports = ['Rick', 'Morty'] module.exports = new Date() // 1. override module.exports object with function expression module.exports = () => { console.log('Wubba-lubba-dub-dub!') } // 2. assign function expression as method of exports module.exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } class Rick { constructor () { this.greet = 'Wubba-lubba-dub-dub!' } callRick () { console.log(this.greet) } } // 3. export new class(function) instance module.exports = new Rick() // 4. export class(function) itself module.exports = Rick // 5. export multiple modules in single export const Morty = { callMorty: () => console.log('Oh Geez!') } module.exports = { Rick, Morty } // 0. console.log(require('./rickAndMorty')) // 1 console.log(require('./rickAndMorty')) // 'R&M' console.log(require('./rickAndMorty')) // {name: 'Rick'} console.log(require('./rickAndMorty')) // ['Rick', 'Morty'] console.log(require('./rickAndMorty')).now() // 1495441119790 // 1. const callRick = require('./callRick') callRick() // 2. const callRick = require('./callRick').callRick callRick() // 3. const Rick = require('./rick') Rick.greet = 'shum-shum-schlippety-dop!' Rick.callRick() const Rick = require('./rick') Rick.callRick() // 4. const Rick = require('./rick') const rick = new Rick() rick.callRick() // 5. const rickAndMorty = require('./rickAndMorty') const morty = rickAndMorty.Morty morty.callMorty() const rick = new rickAndMorty.Rick() rick.callRick()
  66. MODULES - PATTERNS // 0. export all things! module.exports =

    1 module.exports = 'R&M' module.exports = {name: 'Rick'} module.exports = ['Rick', 'Morty'] module.exports = new Date() // 1. override module.exports object with function expression module.exports = () => { console.log('Wubba-lubba-dub-dub!') } // 2. assign function expression as method of exports module.exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } class Rick { constructor () { this.greet = 'Wubba-lubba-dub-dub!' } callRick () { console.log(this.greet) } } // 3. export new class(function) instance module.exports = new Rick() // 4. export class(function) itself module.exports = Rick // 5. export multiple modules in single export const Morty = { callMorty: () => console.log('Oh Geez!') } module.exports = { Rick, Morty } // 0. console.log(require('./rickAndMorty')) // 1 console.log(require('./rickAndMorty')) // 'R&M' console.log(require('./rickAndMorty')) // {name: 'Rick'} console.log(require('./rickAndMorty')) // ['Rick', 'Morty'] console.log(require('./rickAndMorty')).now() // 1495441119790 // 1. const callRick = require('./callRick') callRick() // 2. const callRick = require('./callRick').callRick callRick() // 3. const Rick = require('./rick') Rick.greet = 'shum-shum-schlippety-dop!' Rick.callRick() const Rick = require('./rick') Rick.callRick() // 4. const Rick = require('./rick') const rick = new Rick() rick.callRick() // 5. const rickAndMorty = require('./rickAndMorty') const morty = rickAndMorty.Morty morty.callMorty() const rick = new rickAndMorty.Rick() rick.callRick()
  67. MODULES - PATTERNS // 0. export all things! module.exports =

    1 module.exports = 'R&M' module.exports = {name: 'Rick'} module.exports = ['Rick', 'Morty'] module.exports = new Date() // 1. override module.exports object with function expression module.exports = () => { console.log('Wubba-lubba-dub-dub!') } // 2. assign function expression as method of exports module.exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } class Rick { constructor () { this.greet = 'Wubba-lubba-dub-dub!' } callRick () { console.log(this.greet) } } // 3. export new class(function) instance module.exports = new Rick() // 4. export class(function) itself module.exports = Rick // 5. export multiple modules in single export const Morty = { callMorty: () => console.log('Oh Geez!') } module.exports = { Rick, Morty } // 0. console.log(require('./rickAndMorty')) // 1 console.log(require('./rickAndMorty')) // 'R&M' console.log(require('./rickAndMorty')) // {name: 'Rick'} console.log(require('./rickAndMorty')) // ['Rick', 'Morty'] console.log(require('./rickAndMorty')).now() // 1495441119790 // 1. const callRick = require('./callRick') callRick() // 2. const callRick = require('./callRick').callRick callRick() // 3. const Rick = require('./rick') Rick.greet = 'shum-shum-schlippety-dop!' Rick.callRick() const Rick = require('./rick') Rick.callRick() // 4. const Rick = require('./rick') const rick = new Rick() rick.callRick() // 5. const rickAndMorty = require('./rickAndMorty') const morty = rickAndMorty.Morty morty.callMorty() const rick = new rickAndMorty.Rick() rick.callRick()
  68. MODULES - PATTERNS // 0. export all things! module.exports =

    1 module.exports = 'R&M' module.exports = {name: 'Rick'} module.exports = ['Rick', 'Morty'] module.exports = new Date() // 1. override module.exports object with function expression module.exports = () => { console.log('Wubba-lubba-dub-dub!') } // 2. assign function expression as method of exports module.exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } class Rick { constructor () { this.greet = 'Wubba-lubba-dub-dub!' } callRick () { console.log(this.greet) } } // 3. export new class(function) instance module.exports = new Rick() // 4. export class(function) itself module.exports = Rick // 5. export multiple modules in single export const Morty = { callMorty: () => console.log('Oh Geez!') } module.exports = { Rick, Morty } // 0. console.log(require('./rickAndMorty')) // 1 console.log(require('./rickAndMorty')) // 'R&M' console.log(require('./rickAndMorty')) // {name: 'Rick'} console.log(require('./rickAndMorty')) // ['Rick', 'Morty'] console.log(require('./rickAndMorty')).now() // 1495441119790 // 1. const callRick = require('./callRick') callRick() // 2. const callRick = require('./callRick').callRick callRick() // 3. const Rick = require('./rick') Rick.greet = 'shum-shum-schlippety-dop!' Rick.callRick() const Rick = require('./rick') Rick.callRick() // 4. const Rick = require('./rick') const rick = new Rick() rick.callRick() // 5. const rickAndMorty = require('./rickAndMorty') const morty = rickAndMorty.Morty morty.callMorty() const rick = new rickAndMorty.Rick() rick.callRick()
  69. MODULES - EXPORTS VS MODULE.EXPORTS (function (exports, require, module, __filename,

    __dirname) { // your code here…. }); fn(module.exports, require, module, filename, dirname)
  70. MODULES - EXPORTS VS MODULE.EXPORTS (function (exports, require, module, __filename,

    __dirname) { // your code here…. }); fn(module.exports, require, module, filename, dirname) exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } console.log(exports) // { callRick: [Function] } console.log(module.exports) // { callRick: [Function] }
  71. MODULES - EXPORTS VS MODULE.EXPORTS (function (exports, require, module, __filename,

    __dirname) { // your code here…. }); fn(module.exports, require, module, filename, dirname) exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } console.log(exports) // { callRick: [Function] } console.log(module.exports) // { callRick: [Function] } exports module.exports alias {}
  72. MODULES - EXPORTS VS MODULE.EXPORTS (function (exports, require, module, __filename,

    __dirname) { // your code here…. }); fn(module.exports, require, module, filename, dirname) exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } console.log(exports) // { callRick: [Function] } console.log(module.exports) // { callRick: [Function] } exports = () => { console.log('Wubba-lubba-dub-dub!') } console.log(exports) // [Function] console.log(module.exports) // {} Be careful exports module.exports alias {}
  73. MODULES - EXPORTS VS MODULE.EXPORTS (function (exports, require, module, __filename,

    __dirname) { // your code here…. }); fn(module.exports, require, module, filename, dirname) exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } console.log(exports) // { callRick: [Function] } console.log(module.exports) // { callRick: [Function] } exports = () => { console.log('Wubba-lubba-dub-dub!') } console.log(exports) // [Function] console.log(module.exports) // {} Be careful Error: callRick is not a function exports module.exports alias {}
  74. MODULES - EXPORTS VS MODULE.EXPORTS (function (exports, require, module, __filename,

    __dirname) { // your code here…. }); fn(module.exports, require, module, filename, dirname) exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } console.log(exports) // { callRick: [Function] } console.log(module.exports) // { callRick: [Function] } exports = () => { console.log('Wubba-lubba-dub-dub!') } console.log(exports) // [Function] console.log(module.exports) // {} Be careful Error: callRick is not a function module.exports exports by reference Object exports module.exports alias {}
  75. MODULES - EXPORTS VS MODULE.EXPORTS (function (exports, require, module, __filename,

    __dirname) { // your code here…. }); fn(module.exports, require, module, filename, dirname) exports.callRick = () => { console.log('Wubba-lubba-dub-dub!') } console.log(exports) // { callRick: [Function] } console.log(module.exports) // { callRick: [Function] } exports = () => { console.log('Wubba-lubba-dub-dub!') } console.log(exports) // [Function] console.log(module.exports) // {} Be careful Error: callRick is not a function module.exports exports by reference Object module.exports exports Object Object = exports module.exports alias {}
  76. MODULES - REQUIRE ALL TOGETHER require(X) from module at path

    Y 1. If X is a core module, a. return the core module b. STOP 2. If X begins with '/' a. set Y to be the filesystem root 3. If X begins with './' or '/' or '../' a. LOAD_AS_FILE(Y + X) b. LOAD_AS_DIRECTORY(Y + X) 4. LOAD_NODE_MODULES(X, dirname(Y)) 5. THROW "not found" LOAD_AS_FILE(X) 1. If X is a file, load X as JavaScript text. STOP 2. If X.js is a file, load X.js as JavaScript text. STOP 3. If X.json is a file, parse X.json to a JavaScript Object. STOP 4. If X.node is a file, load X.node as binary addon. STOP LOAD_INDEX(X) 1. If X/index.js is a file, load X/index.js as JavaScript text. STOP 2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP 3. If X/index.node is a file, load X/index.node as binary addon. STOP LOAD_AS_DIRECTORY(X) 1. If X/package.json is a file, a. Parse X/package.json, and look for "main" field. b. let M = X + (json main field) c. LOAD_AS_FILE(M) d. LOAD_INDEX(M) 2. LOAD_INDEX(X) LOAD_NODE_MODULES(X, START) 1. let DIRS=NODE_MODULES_PATHS(START) 2. for each DIR in DIRS: a. LOAD_AS_FILE(DIR/X) b. LOAD_AS_DIRECTORY(DIR/X) NODE_MODULES_PATHS(START) 1. let PARTS = path split(START) 2. let I = count of PARTS - 1 3. let DIRS = [] 4. while I >= 0, a. if PARTS[I] = "node_modules" CONTINUE b. DIR = path join(PARTS[0 .. I] + "node_modules") c. DIRS = DIRS + DIR d. let I = I - 1 5. return DIRS
  77. NPM - GLOSSARY NPM - Node Package Manager, comes with

    node by default Package - Code managed and maintain by package management system Package Management System - Software that automates installing and updating packages, deals with what version you have or need, and manages dependencies Dependency - Code that another set of code depends on to function node_modules - A folder in your project root that contains all installed packages and dependencies package.json - A file contains meta data about your app or module. includes the list of dependencies to install from NPM when running `npm install` Yarn - A client built on top of NPM, keeps consistency across all installations by adding yarn.lock file, faster than NPM (comparing to v4)
  78. NPM - INSTALL Create initial package.json $ npm init -y

    $ npm install something Install Installs into local node_modules directory In your project root (ex. /Home/myApp) Home / myApp / node_modules / something
  79. NPM - INSTALL Create initial package.json $ npm init -y

    $ npm install something Install Installs into local node_modules directory In your project root (ex. /Home/myApp) Home / myApp / node_modules / something $ npm install -g something install globally (use case for executables)
  80. NPM - INSTALL Create initial package.json $ npm init -y

    $ npm install something Install Installs into local node_modules directory In your project root (ex. /Home/myApp) Home / myApp / node_modules / something In /Users/ofer/myApp/app.js const something = require('something') • /Users/ofer/myApp/node_modules/something.js • /Users/ofer/node_modules/something.js • /Users/node_modules/something.js • /node_modules/something.js $ npm install -g something install globally (use case for executables)
  81. NPM - PACKAGE.JSON { "name": "nodejs-course-2017", "version": "1.0.0", "description": "code

    examples and exercises for node.js course", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", "url": "git+https://github.com/xl8/nodejs-course-2017.git" }, "keywords": [], "author": "[email protected]", "license": "MIT", "bugs": { "url": "https://github.com/xl8/nodejs-course-2017/issues" }, "homepage": "https://github.com/xl8/nodejs-course-2017#readme", "dependencies": { "express": "^4.15.3" } } version number
  82. NPM - SEMANTIC VERSIONING "express": "^4.15.3" 4 15 3 major

    minor patch major minor patch caret(^) tilde(~) - breaking change - backwards compatible new functionality - old functionality deprecated, but operational - large internal refactor - bug fix 4.*.* 4.15.*
  83. EXPRESS "a minimal and flexible node.js web application framework" const

    http = require('http') http.createServer((req, res) => { // Homepage if (req.url === '/') { res.writeHead(200, { 'Content-Type': 'text/html' }) res.end('Welcome to the homepage!') } // About page else if (req.url === '/about') { res.writeHead(200, { 'Content-Type': 'text/html' }) res.end('Welcome to the about page!') } // 404 else { res.writeHead(404, { 'Content-Type': 'text/plain' }) res.end('404 error! File not found.') } }).listen(1337, 'localhost')
  84. EXPRESS "a minimal and flexible node.js web application framework" const

    express = require('express') const app = express() // Homepage app.get('/', (req, res) => { res.status(200).send('Welcome to the homepage!') }) // About page app.get('/about', (req, res) => { res.status(200).send('Welcome to the about page!') }) // 404 app.get('/*', (req, res) => { res.status(404).send('404 error! File not found.') }) app.listen(1337) const http = require('http') http.createServer((req, res) => { // Homepage if (req.url === '/') { res.writeHead(200, { 'Content-Type': 'text/html' }) res.end('Welcome to the homepage!') } // About page else if (req.url === '/about') { res.writeHead(200, { 'Content-Type': 'text/html' }) res.end('Welcome to the about page!') } // 404 else { res.writeHead(404, { 'Content-Type': 'text/plain' }) res.end('404 error! File not found.') } }).listen(1337, 'localhost')
  85. EXPRESS Client Server socket HTTP Request HTTP Response 199.203.181.36 64.233.163.104

    Basics reminder: TCP/IP Client-Server Model port: 80 443
  86. EXPRESS Client Server socket HTTP Request HTTP Response 199.203.181.36 64.233.163.104

    Basics reminder: TCP/IP Client-Server Model Node.js HTTP module Request Express Response port: 80 443
  87. EXPRESS Client Server socket HTTP Request HTTP Response 199.203.181.36 64.233.163.104

    Basics reminder: TCP/IP Client-Server Model {Request} {Response} Next() Node.js HTTP module Request Express Response port: 80 443
  88. EXPRESS Client Server socket HTTP Request HTTP Response 199.203.181.36 64.233.163.104

    Basics reminder: TCP/IP Client-Server Model {Request} {Response} Next() Middleware body parser Node.js HTTP module Request Express Response port: 80 443
  89. EXPRESS Client Server socket HTTP Request HTTP Response 199.203.181.36 64.233.163.104

    Basics reminder: TCP/IP Client-Server Model {Request} {Response} Next() next cookie parser Middleware body parser Node.js HTTP module Request Express Response port: 80 443
  90. EXPRESS Client Server socket HTTP Request HTTP Response 199.203.181.36 64.233.163.104

    Basics reminder: TCP/IP Client-Server Model {Request} {Response} Next() next cookie parser Middleware body parser logger next Node.js HTTP module Request Express Response port: 80 443
  91. EXPRESS Client Server socket HTTP Request HTTP Response 199.203.181.36 64.233.163.104

    Basics reminder: TCP/IP Client-Server Model {Request} {Response} Next() next cookie parser Routes next Router Middleware body parser logger next Node.js HTTP module Request Express Response port: 80 443
  92. EXPRESS Client Server socket HTTP Request HTTP Response 199.203.181.36 64.233.163.104

    Basics reminder: TCP/IP Client-Server Model {Request} {Response} Next() next cookie parser Routes next Router multer /upload Middleware body parser logger next Node.js HTTP module Request Express Response port: 80 443
  93. EXPRESS Client Server socket HTTP Request HTTP Response 199.203.181.36 64.233.163.104

    Basics reminder: TCP/IP Client-Server Model {Request} {Response} Next() next cookie parser Routes next Router multer /upload next request handler Middleware body parser logger next Node.js HTTP module Request Express Response port: 80 443
  94. EXPRESS Client Server socket HTTP Request HTTP Response 199.203.181.36 64.233.163.104

    Basics reminder: TCP/IP Client-Server Model {Request} {Response} Next() next cookie parser Routes next Router multer /upload next request handler Middleware body parser logger next Node.js HTTP module Request Express Response error handling MW err port: 80 443