Click to view this presentation.
-
Explain the Use Case for NodeJS
-
Use NodeJS to Execute JavaScript
-
Create and Use Node Modules
-
Use NPM to Install External Packages
- Transitioning to Unit 3
- Facts about NodeJS
- Why the Enthusiasm for Node?
- Rails or Node?
- Why is Node so Performant?
- Using Node to Execute JavaScript
- NodeJS Modules
- Our First Module
- NPM - Node Package Manager
-
In Unit 2, you begun your journey of becoming a full-stack developer.
-
Although we're heading off the Rails, rest assured that much of what you've learned applies to full-stack development as a whole...
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
- MVC (Model/View/Controller) Architectural Pattern
- RESTfull Routing & Mapping to Data CRUD
- Relational Data Modeling
- Data Manipulation using an ORM such as ActiveRecord
- Server-side View Templating
- Authentication & Authorization
- Deployment
-
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.
-
Learning new technologies is always a challenge.
-
Secondly, Node/Express, unlike with Rails, does not subscribe to the Convention over Configuration methodology, which translates into:
- More code to write to accomplish even the most basic of tasks
- Wildly varying ways to structure applications
- More complexity - thanks to more flexibility
- Varying degree of modularization of code
-
Basically, Node/Express apps are the...
-
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.
-
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.
- Let's take a look at Node's interactive Node's REPL (Read-Eval-Print-Loop). Think of Node's REPL as Node's version of Ruby's IRB. 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.
-
Node is an open source project governed by the NodeJS Foundation with board representation from companies such as:
- PayPal
- Microsoft
- GoDaddy
- IBM
- Red Hat
- Intel
-
There is also a Technical Steering Committee independent from the Board.
-
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.
-
Packages are to Node, as Gems are to Ruby.
-
Packages are managed using a package manager called npm which is installed with Node.
-
Node's package ecosystem is the largest open source ecosystem in the world.
-
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.
-
The improvements in server performance and developer productivity result in businesses saving money.
-
Businesses saving money results in wide adoption:
- Wide adoption of Node results in more demand for Node developers:
-
Quickest path to building an app with full CRUD.
-
Better at working with complex data relationships - ActiveRecord rocks!
-
When full page refreshes aren't an issue.
-
Easier to program because synchronous programming is more straightforward than async programming.
-
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.
- First, it's important to understand how time consuming and "expensive" data Input/Output operations are:
- Node's Asynchronous / Event-driven design enables non-blocking Input/Output:
-
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.
Rails (Synchronous Programming)
-
Each line of code must finish before the next line is executed. Sounds logical until you consider 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.
NodeJS (Asynchronous Programming)
-
Node is asynchronous and non-blocking, that means that it is designed not wait for those notoriously slow I/O operations to complete before it moves on.
-
Your friend, the callback function, enables this pattern. When our code calls a method involving I/O, we also provide a callback function to be, well, "called back", when the I/O operation is complete.
-
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?
Let's see how we can run a JavaScript program in Node:
$ mkdir first-node
$ cd first-node
$ touch main.js
$ code .
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.
-
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
thefives
array.
- Defines an empty array named
-
Use Node to execute your program.
-
Modules in Node allow us to organize and reuse JavaScript code.
-
Node itself comes with several core modules, such as the
http
andfs
modules. -
There are thousands of open-source modules available.
-
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.
-
You can put your app's custom module files in any folder within your project. This allows us to organize our code inside folders named
models
,routes
, etc.
-
Inside of our modules, Node automatically provides a special object named
module.exports
and a "shortcut" variable that points tomodule.exports
named what else -exports
. -
We can attach our module's functionality to
module.exports
orexports
:module.exports.myNumber = 123; // same as above exports.myNumber = 123; // add as many properties as you wish exports.sayHi = function() { console.log('Hi'); };
-
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
thatrequire
s this module references the function!
-
Wherever and whenever we need to use our custom module, 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.
-
require
basically "turns into" whatevermodule.exports
is. This is true whether we "attach" properties the originalmodule.exports
orexports
object, or assign to it a function, array or whatever:// 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'
-
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.
- Provides an array named
-
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
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) {
return exports.weekdays[dayNo < 0 || dayNo > 6 ? defaultDay : 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.
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
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) );
}
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...
-
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? -
Does the variable name we use need to match the name of the module?
continued on next slide...
-
Will this work?
// 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
-
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.
-
Working with packages in Node is very similar to working with gems in Ruby:
Ruby Node gem install ...
npm install ...
bundle install
(works withGemfile
)npm install
(works withpackage.json
)
-
Similar to how Rails has a
Gemfile
to track gems that an application depends on, Node apps have apackage.json
file that does the same thing. -
Why is tracking an application's dependencies in a separate file important?
-
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
-
Now, let's use
npm
to install one of Node's packages:$ npm install request
-
Take a look and you will find that a
node_modules
folder has been added to your project and that it contains a folder for therequest
module. -
Note: it's recommended that
node_modules
be added to your.gitignore
file.
-
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": "My first node app",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "You <[email protected]>",
"license": "MIT",
"dependencies": {
"request": "^2.69.0"
},
"devDependencies": {
"gulp": "^3.9.1"
}
}
-
The
package.json
file works a like aGemfile
in that we can install the dependencies from it. This is almost always necessary after cloning a repo or using the starter code for a given lesson. -
Let's delete our
node_modules
file:$ rm -rf node_modules
-
Now we can install our app's dependencies like this:
$ npm install
Witness the return of
node_modules
!
-
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!