Skip to content

Instantly share code, notes, and snippets.

@jim-clark
Last active October 22, 2018 16:58
Show Gist options
  • Save jim-clark/f9ef10448ab179945c3d1ad678faea26 to your computer and use it in GitHub Desktop.
Save jim-clark/f9ef10448ab179945c3d1ad678faea26 to your computer and use it in GitHub Desktop.

Click to view this presentation.




Intro to NodeJS


Learning Objectives


  • Explain the Use Case for NodeJS

  • Use NodeJS to Execute JavaScript

  • Create and Use Node Modules

  • Use NPM to Install External Packages


Roadmap


  • Transitioning to Unit 3
  • Facts about NodeJS
  • Why the Enthusiasm for Node?
  • Django or Node?
  • Why is Node so Performant?
  • Using Node to Execute JavaScript
  • NodeJS Modules
  • Our First Module
  • NPM - Node Package Manager

Transitioning to Unit 3


  • In Unit 2, you begun your journey of becoming a full-stack developer.

  • Although we're moving on from Django, rest assured that much of what you've learned applies to full-stack development as a whole...


Transitioning to Unit 3


The following concepts we've covered in class will continue to serve you well:

  • OOP - Design, Encapsulation of Data (attributes) & Behavior (methods) and Inheritance)
  • HTTP and the Browser-Request/Server-Response Cycle
  • Relational Data Design
  • Data Manipulation using an ORM
  • Server-side Templating
  • Authentication & Authorization
  • Deployment

Unit 3 - Technologies


  • In Unit 3, we will delve into the world of:

    • NodeJS - An operating environment that executes our old friend - JavaScript
    • Express - The most popular web framework for NodeJS
    • MongoDB - A NoSQL, document-based database system
  • The three technologies above account for three of the four technologies involved in the MEAN and MERN Solution Stacks.


So, the Magic of Django is Leaving the Station...


Without the Magic of Django,
is this Going to be Difficult?


  • Yes, learning new technologies is always a challenge!

  • Secondly, Node/Express, unlike with Django, is minimalistic and unopinionated, which translates into:

    • More code to write to accomplish even the most basic of tasks
    • Wildly varying ways to structure applications
    • Varying degree of modularization of code
  • Basically, Node/Express apps are the...



What is NodeJS?



Facts about NodeJS


  • An open source, cross-platform, runtime environment that executes JavaScript, primarily on the server-side.

  • Created in 2009 by Ryan Dahl with Joyent, Inc.

  • Written primarily in C++, not JS!

  • Uses Google's V8 JavaScript Engine to compile JS programs into machine code.


Facts about NodeJS (cont.)


  • The runtime environment for JS is different in Node than that in the browser, primarily because there is no DOM.

  • Although NodeJS is primarily thought of as a runtime for server-side JavaScript, it is also used extensively for running client-side utility programs.


Facts about NodeJS (cont.)

  • Node is an open source project governed by the NodeJS Foundation with board representation from companies such as:

    • PayPal
    • Microsoft
    • Google
    • GoDaddy
    • IBM
    • Red Hat
    • Intel
  • There is also a Technical Steering Committee independent from the Board.


Facts about NodeJS (cont.)


  • Extremely lightweight. Only low-level "core" modules for networking, filesystem access, etc. are baked-in.

  • Node's functionality is extended via open source libraries called packages. Packages usually contain a module of code that we can require (use) in our own modules, but sometimes a package installs command line interface (CLI) tools.


Facts about NodeJS (cont.)


  • Node has packages, just like Python does.

  • Python used pip to manage packages. In Node we use a package manager called npm which is installed with Node.

  • Node's package ecosystem is the largest open source ecosystem in the world.


Node's REPL

  • Similar to Python, when you type just node in Terminal, you enter Node's interactive REPL (Read-Eval-Print-Loop). Typing node in terminal launches it:
$ node
> 10 + 5
15
> function sayHello() {
... console.log('Hello');
... }
undefined
> sayHello()
Hello
undefined
> var http = require('http');
undefined
> http
[ a large JS object representing Node's 'http' module ]

Press control-c twice to exit REPL.


Why the Enthusiasm for Node?


Why the Enthusiasm for Node?


  • First and foremost, performance - businesses can handle more traffic with less hardware!

  • Secondly, developer synergy. Because a developer can use JS on client & server, becoming a full-stack dev is more obtainable and companies can better utilize their developer resources across the front and back-ends.


Why the Enthusiasm for Node? (cont.)

  • The improvements in server performance and developer productivity result in businesses saving money.

  • Businesses saving money results in wide adoption:


Why the Enthusiasm for Node? (cont.)


  • Lastly, and most importantly, wide adoption of Node results in strong demand for Node developers!


Django or Node?


Why Choose Django?


  • Quicker path to building an app with full CRUD.

  • Better at working with complex data relationships - the Django ORM rocks!

  • When full page refreshes aren't an issue.

  • Easier to program because synchronous programming is more straightforward than async programming.


Why Choose Node?


  • JavaScript everywhere!

  • When high performance and high capacity matter.

  • Designed with modern realtime, mobile and Single Page Applications in mind - easier to avoid full page refreshes.


Why is Node so Performant?

  • First, it's important to understand how time consuming ("expensive") Input/Output operations are:


Why is Node so Performant? (cont.)

  • Node's Asynchronous / Event-driven design enables non-blocking Input/Output:


Why is Node so Performant? (cont.)


  • This technical jargon basically results in a Node server capable of supporting tens of thousands of concurrent connections!

  • For more information, check the references at the end of this presentation.


Synchronous vs. Asynchronous


Django or Rails (Synchronous Programming)

  • Each line of code must finish before the next line is executed. Sounds logical until you consider that if the line of code involves an I/O operation (network, database, or file system call) that your program will spend most of its time waiting until the I/O operation is completed.


Synchronous vs. Asynchronous


NodeJS (Asynchronous Programming)

  • Node's I/O is non-blocking. That means that it is designed not wait for those notoriously slow I/O operations to complete before it moves on.

  • Callback functions enable this async programming model. When our code calls a method involving I/O, the rest of the program keeps running and the callback is put in the event queue when I/O operation finishes.


Questions - What is NodeJS?


  • True or false - Node itself is written in JavaScript.

  • Is NodeJS a programming language?

  • What is the primary reason why Node/Express applications are so performant?

  • Is
    var elem = document.getElementById('my-list');
    a valid JavaScript statement in a Node app?


Now that you've learned the use case for Node, let's see how it can run JavaScript programs


Using Node to Execute JavaScript


Let's see how we can run a JavaScript program in Node:

$ mkdir first-node
$ cd first-node
$ touch main.js
$ code .

Using Node to Execute JavaScript


Toss in a little JavaScript into main.js:

function multiply(x, y) {
  return x * y;
}

var n = multiply(5, 8);

console.log(n);

Now use Node to run main.js:

$ node main
40

Note how you don't need to include the "js" file extension.


Practice (5 mins)
Use Node to Execute JavaScript


  • To practice, and to help get back into the JavaScript "mindset", replace the code in main.js with code that:

    • Defines an empty array named fives.
    • Uses a for loop to loop through the numbers 1 through 100.
    • Within the loop's code block, if the current value of the loop variable is evenly divisible by 5, add it to the fives array.
    • After the loop has completed, console.log the fives array.
  • Use Node to execute your program.


So far, so good!
Now let's learn about Modules


NodeJS Modules


  • Modules in Node allow us to organize and reuse JavaScript code.

  • Node itself comes with several core modules, such as the http and fs modules.

  • There are thousands of open-source modules available.


NodeJS Modules (cont.)


  • In our own programs, we organize our code into modules.

  • Each module will be contained in its own file - there is a one-to-one mapping between a file and a module. This was exactly the same as in Python.

  • You can put your app's modules (files) in any folder within your project. This allows us to organize our code inside folders named models, routes, etc.


NodeJS Modules (cont.)


  • Unlike in Python modules, where every module variable, function and class were available by default to be imported by another module, Node modules limit what is available to whatever an implicit property, module.exports, is set to or holds.

  • Also, Node's modules use a require function instead of importto import whatever is exported by the module...


NodeJS Modules (cont.)


  • For example, say you have a module (file) named colors.js:

     module.exports = ['red', 'green', 'blue'];
  • Any other module that wanted that array of colors can require it as follows:

     var basicColors = require('./colors');
     // basicColors now references the array exported by colors.js

NodeJS Modules (cont.)



Modules exports Their Functionality

  • Inside of our modules, Node automatically provides a special object named module.exports and a "shortcut" variable that points to module.exports named what else - exports.

  • We can attach our module's functionality to module.exports or exports:

     module.exports.myNumber = 123;
     // same as above
     exports.myNumber = 123;
     
     // add as many properties as you wish
     exports.sayHi = function() { console.log('Hi'); };

Modules exports Their Functionality


  • If we want to assign a single piece of functionality without using a property, be sure to use module.exports:

     module.exports = function() { console.log('Hi'); };
     // Below will not work due to breaking the object reference
     // exports = function() { console.log('Hi'); };
  • Now, a var that requires this module references the function!


Using the require Method


  • Wherever and whenever we need access to a custom module's module.exports, we just require the module file, without the file extension, using a relative path.

  • Note that the module is loaded only once, even if it is "required" multiple times.


Using the require Method (cont.)


  • require basically "turns into" whatever module.exports is - PERIOD:

     // my-module attached a myNumber property to module.exports
     var myMod = require('./my-module');
     console.log(myMod.myNumber);  // outputs 123
     
     // module.exports was assigned a sayHi function
     var sayHi = require('./my-module');
     console.log( sayHi() );  // outputs 'Hi'

Modules - Remember This


requires(...)

Equals whatever

module.exports

Is set to!!!


Our First Module


  • Together, let's create a module that:

    • Provides an array named weekdays containing two-character names of the days of the week.
    • Provides a function named getWeekday that accepts a number from
      0 to 6 and returns the name; where 0 = 'Su'.
    • If an invalid number is passed in, assume a value of 1.
  • Let's put our module inside of a "utilities" folder and name it "days-of-week.js":

     $ mkdir utilities
     $ touch utilities/days-of-week.js

Our First Module (cont.)

The code will look like this:

// days-of-week.js

// This is a local variable in scope to this module only
var defaultDay = 1;

// Exporting the weekdays array
module.exports.weekdays = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];

// You can "attach" properties directly on "exports".
// However, "assigning" directly to exports breaks!
exports.getWeekday = function(dayNo) {
	if (dayNo < 0 || dayNo > 6) dayNo = defaultDay;
	return exports.weekdays[dayNo];
}

console.log("days-of-week module has been loaded");

Note that in Node, all variables defined are local to that module - they will not pollute the global scope.


Our First Module (cont.)


Use our "days-of-week" module in "main.js":

// main.js
	
var dow = require('./utilities/days-of-week');
	
// Outputs the weekdays array
console.log(dow.weekdays);
	
// Outputs "Fr"
console.log(dow.getWeekday(5));

Run "main.js" with Node:

> node main


Practice - Modules #1 (10 mins)


Create two separate modules:

A module named "random" that has a function assigned to the module.exports and returns a random number, as an integer, between two numbers provided, inclusive, as arguments; so that we could use it in our program like this:

var random = require('./utilities/random');
for (var i = 0; i < 10; i++) {
	console.log( random(100, 200) );
}

Practice - Modules #2 (10 mins)


A module named "circle" that exports two functions:

  • area: Computes the area of a circle (radius squared X Pi), with the radius provided as an argument.
  • circumference: Computes the circumference of a circle (radius X 2 X Pi), with the radius provided as an argument.
  • Hint: This is JS, so Math.PI is available.
var circle = require('./utilities/circle');
console.log( circle.area(50) );  // 7853.98...
console.log( circle.circumference(75) );  // 471.23...

Questions - Modules

  • What are modules used for in Node?

  • How many modules can be defined in a file?

  • What is the special object we use in our module to attach or assign functionality to?

  • How many times can we require a module in our program?

continued on next slide...


Questions - Modules (cont.)


  • Wy won't this work as intended?

     // in module file named add.js
     exports = function (x, y) { return x + y };
     
     // in other file
     var add = require('./add');
     console.log( add(1, 2) );

Now that you've created and used your own modules, let's see how we can install open-source packages and use the modules they contain


NPM - Node Package Manager


  • Node uses a package management system to distribute open-source packages called Node Package Manager (npm).

  • Usually a package distributes a Node module, however, sometimes the package distributes a CLI instead of a module we would use in our program.


NPM - Node Package Manager (cont.)


  • Node programs use a package.json file that tracks the installed modules that the app depends upon.

  • Why is tracking an application's dependencies in a separate file important?


NPM - Node Package Manager (cont.)


  • If you start a Node app from scratch, the first thing you should do is create the package.json file by entering the following command:

     $ npm init
  • It's okay to accept all of the default settings. To accept the defaults without being prompted, you can run the command as follows:

     $ npm init -y

NPM - Node Package Manager (cont.)

  • Now, let's use npm to download and install a package:

     $ npm install request
  • There is now a node_modules folder that contains a folder for the request module many other dependencies.

  • There's also a new package-lock.json file that npm uses to track dependencies and unlike package.json, should not be edited.

  • Note: it's highly recommended that node_modules be added to your .gitignore file.


NPM - Node Package Manager (cont.)

  • We can now require the `request` module in our "main.js" and make HTTP requests:

// Don't specify path when module is in node_modules
var request = require('request');
request('http://jsonplaceholder.typicode.com/users', function(err, res, body) {
	console.log(body);
});
  • Why do we need to provide a callback?

  • Note the first parameter in the callback is err. This "error-first" callback signature is prevalent throughout Node.

  • Use Node to execute main.js and check out the result!


### NPM - Node Package Manager (cont.)
  • Examining the `packages.json` file reveals that it's structured like this...

{
  "name": "first-node",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Jim Clark <[email protected]>",
  "license": "MIT",
  "dependencies": {
    "request": "^2.88.0"
  }
}

NPM - Node Package Manager (cont.)


  • The package.json is used to install a project's dependencies.

  • Installing dependencies is necessary after cloning a repo or when using the starter code for a lesson.

  • To demonstrate this, first delete the node_modules file, then...


NPM - Node Package Manager (cont.)


  • Now we can install our app's dependencies like this:

     $ npm install

    Witness the return of node_modules!


Conclusion


  • In the next lesson, you will use one of the most popular Node modules, Express, that turns Node into a capable web server.

  • Questions?

  • Take a break!


References


NodeJS Homepage

Node Package Manager

Blocking/Non-Blocking, Async/Sync

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment