node.js
An intro to node.js
http://nodejs.org
What is node.JS
A server side JavaScript engine written by Ryan Dahl
- Enjoys the fruits of the browsers war.
Fast JavaScript VMs and JIT. Faster than the Ruby VM or
the Python interpreter
- Well suited for high I/O scenarios
web like request/response, reading files, network streams, or
streams in general
- Designed with async in mind and non blocking I/O
- Active community generating tens of thousands
extension modules
Node’s Goal is to provide an easy way to build scalable network programs
On the device node enables writing light web like services efficiently and quickly
Why node.js
- Non blocking I/O
- Code can be shared between the client and the server
- 60,000+ extension modules
- Cross platform and supported by Microsoft
Our team increased its coding velocity by x10 fold
Hello Node
var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello Node!\n'); }).listen(1337);
console.log('Server running at http://127.0.0.1:1337/');
The most basic http server implementation.
organizing code in modules
Node uses the CommonJS approach for organizing code.
The developer can create extension units called modules for code reuse, maintainability and testing.
// file utils // initilization code goes here var moduleWideVariable = 'This can only be accessed by the module members'; // the exports object will be the one being returned by the require function exports.gzipFileStream = function(filename) { // lazy loading the actual needed modules var fs = require('fs'); var zlip = require('zlib'); var fileStream = fs.createReadStream(filename); var gzip = zlib.createGzip(); return fileStream.pipe(gzip); };
ORGANIZING CODE IN MODULES
- Modules are loaded using the global require method (specific to node.js)
- The require method accepts a name of a module, and returns a JavaScript object representing the module.
- It accepts both a full file path, as well as a folder that contains a package.json file.
- 2 types of modules:
- JavaScript
- Native bindings written in c++ (it's just a DLL with a ".node" extension)
ORGANIZING CODE IN MODULES
Consuming modules is easy:
// fs is a builtin module var fs = require('fs'); // fs has a readFileSync function var data = fs.readFileSync('./data.txt'); // request is an external module var request = require('request'); // it's actually a function, so we can just call it in order to make a request request('http://www.bing.com', function(err, res, body) { // ... });
ORGANIZING CODE IN MODULES
Authoring modules is easy as well:
exports.helloWorld = function {
return 'hello world!';
};
Everything you'll set on the exports object will be exposed to the user of the module.
You can even replace exports with another object (like in request), by setting the module.exports field.
Other than module, and exports, each module also has a built in __filename and __dirname variables.
DEMO
Authoring modules is easy as well:
exports.helloWorld = function {
return 'hello world!';
};
Everything you'll set on the exports object will be exposed to the user of the module.
You can even replace exports with another object (like in request), by setting the module.exports field.
Other than module, and exports, each module also has a built in __filename and __dirname variables.
DEMO
ORGANIZING CODE IN MODULES
Node.js has a bunch of built in modules.
exports.helloWorld = function {
return 'hello world!';
};
Everything you'll set on the exports object will be exposed to the user of the module.
You can even replace exports with another object (like in request), by setting the module.exports field.
Other than module, and exports, each module also has a built in __filename and __dirname variables.
DEMO
Node.js has a bunch of built in modules.
exports.helloWorld = function {
return 'hello world!';
};
Everything you'll set on the exports object will be exposed to the user of the module.
You can even replace exports with another object (like in request), by setting the module.exports field.
Other than module, and exports, each module also has a built in __filename and __dirname variables.
DEMO
node_modules folder
If the module identifier passed to require() is not a native module, and does not begin with '/', '../', or './', then node starts at the parent directory of the current module, and adds /node_modules, and attempts to load the module from that location.
If it is not found there, then it moves to the parent directory, and so on, until the root of the tree is reached.
if not found, it will look for a NODE_PATH environment variable.
Event emitters
Many of the built in constructs in node inherit from the EventEmitter class. This allows developers to register handlers for events in the life of the different objects.
For example a request object.
var http = require('http'); var req = http.get('http://www.bing.com', function(err, res) { res.on('data', function(data) { console.log(data); }); res.on('error', function(err) { console.error('Error in response stream', err); }); res.on('end', function() { console.log('DONE FETCHING bing.com'); }); }); req.end();
Streams
Node supports the notion of streams for abstracting efficient non-blocking access to system resources. Files, Network, Pipes, Crypto are a few examples which node abstracts as streams.
This allows for a powerful chaining syntax that provides the developer with a concise clear code that is highly efficient.
var fs = require('fs'); var zlib = require('zlib'); var http = require('http'); http.createServer(function(req, res) { var fileStream = fs.createReadStream(__dirname + '/static/index.html'); var gzip = zlib.createGzip(); res.writeHead((200, { 'Content-Type': 'text/html', 'Content-Encoding': 'gzip', }); // pipe the file into the gzip stream and right into the response stream // using efficient non-blocking I/O fileStream.pipe(gzip).pipe(res); });
NPM - Node Package Manager
installing packages
mkdir node_modules
npm install async
For DSS we created an internal NPM site http://dss
All the modules appearing in the internal site have been LCA approved or developed by internal Microsoft teams.
Feel free to add internal modules to the internal site. If you need additional open source modules from the public site please let us know and we will run them through LCA and add them to the internal site.
Popular modules
ExpressJS - Web framework
var express = require('express'); var app = express(); app.use(express.bodyParser()); app.get('/hello.txt', function(req, res){ res.send('Hello World'); }); var server = app.listen(3000, function() { console.log('Listening on port %d', server.address().port); });
In DSS we use a lightweight module called middler that offers similar basic functionality.
Async - Flow Control
async.map(['file1','file2','file3'], fs.stat, function(err, results){ // results is now an array of stats for each file }); async.filter(['file1','file2','file3'], fs.exists, function(results){ // results now equals an array of the existing files }); async.parallel([ function(){ ... }, function(){ ... } ], callback); async.series([ function(){ ... }, function(){ ... } ]);
PeRFORMANCE - Buffer
- Use node's built-in Buffer to hold chunks of data
- Efficient: Buffer uses a pool for small sized buffers (< 8k), and for larger buffers, memory is actually allocated by native code (and not JS), making things much more efficient
- Built-in supports for different encodings
- Could be directly accessed using indexes
// create a new buffer from string, encode as utf8 var buffer = new Buffer("I'm a string!", "utf-8") // print the length of the buffer: console.info(buffer.length) // now, get the first byte: console.log(buffer[0]) // you can even convert to base64! console.info(buffer.toString('base64'))
performance - Streams
- Use streams - to read large data/files in chunks
- But....memory-wise , reading large bulks of data could be more efficient than reading smaller bulks since the memory allocations are more continuous.
Performance -Memory MGMT
- Don't hold anything on the global object unless you have to
- Remember to use the var keyword:
// j is undefined here function func { // good, will hold the var in the scope of func var i = 10; // bad, j is now actually hung on the global j = 10; } func(); // i is undefined here, and j=10 here!
PERFORMANCE - MORE Memory MGMT
- Call CollectGarbage() when necessary to explicitly call the garbage collector to free up memory.
(specific to node.ch/dss. node.js (with v8) has the gc() function when invoked with --expose-gc switch)
- Can be called after large chunks of data were introduced into JS in order to free up memory faster
Copy of node.js
By Nadav Bar
Copy of node.js
A node.js intro course
- 1,485