Modern Server Side
Development with NodeJS
What changed since the 0.10 days
Benjamin Gruenbaum
Benjamin Gruenbaum
• I work @ TipRanks
• NodeJS core collaborator.
• Promises guy, bluebird fan and core contributor.
• I argue with people online.
• StackOverflow guy.
This talk is in 3 parts
The Past
The Present
The Future
Let’s go back to 2009
JavaScript on the Server
JavaScript on the server is an
old idea
Netscape Enterprise Server – 1995
Steve Yegge’s Server – 2008
JavaScript on the server is a
good idea?
Remember, 2008- JavaScript engines are painfully slow.
APIs were nonexistent.
Language was hated.
Suddenly – V8
Google needed fast JavaScript in Chrome –
so JavaScript engines became fast.
This Ryan guy thought… let’s
make a non-blocking server.
As in – no thread “block”s in the user server code.
What can we write this in?
We need a language that doesn’t have file/net APIs yet to get a sane
ecosystem.
JavaScript has no blocking
APIs
The Result –
solving “The 10K Problem”
How: The Event Loop
Threads and OS non-blocking APIs push things into queues
User code runs on a single thread and executes handlers on the queues
Why even write node?
It’s fast enough.
Why even write node?
Server and client in one language
Why even write node?
It was cool
Remember: in 2009 JS is all the hotness
Code Sample: Chat Server
net.createServer(function(socket) {
var user = users.add(socket)
socket.on('data', function(data) { <- Callback
user.sendOthers("> " + data)
});
socket.on('close', function(hadError) { <- Callback
user.leave();
});
}).listen(8000);
Ryan joined Joyent, which
looked over Node
Initially, things worked well –
Node got traction
But… Stagnation started.
No new ES features, even when available in Chrome.
Fast Forward to last year
NodeJS was forked into Io.js
Goal: Modern V8
Goal: Modern APIs
Goal: Inclusivity
Goal: Adopt modern JS
Eventually, io.js won. The
projects merged.
The result of the io.js fork:
Modern V8 version.
NodeJS on top of the io.js fork rather than the
Joyent repo.
Handing over of the Joyent repo to the NodeJS
foundation.
Community governance.
Lots of new features for the community.
Just how different is Node
today?
Current version: Node 7+
Node 0.12 – last year
function persistCriticalFile(cb) {
fs.readFile("criticalFile", function(err, data) {
if(err) return cb(err);
db.persist("collection", process(data), function(err, result) {
if(err) return cb(err);
cb(null, result);
});
});
}
Current version: Node 7+
Node 7 – this year
async function persistCriticalFile(cb) {
const data = await fs.readFileAsync("criticalFile");
return await db.persistAsync("collection", process(data));
}
So – how do we develop with Node 7?
Let’s look at a simple scenario. You want to get the comments to a post
on your site.
- First, from the cache if they’re there.
- If they’re not, from the database.
So – how do we develop with Node 7?
Node 0.x:
app.get('/getComments/:userId', function(req, res){
var userId = req.params.userId;
commentCache.get(userId, function(err, data) {
if(err) {
instrumentation.log(err);
return res.json(err);
}
if(data) return res.json(data);
db.getCommentsByUserId(userId, function(err, data) {
if(err) {
instrumentation.log(err);
return res.status(500).end(err);
}
cache.store(data, function() {});
return res.json(data);
});
});
});
So – how do we develop with Node 7?
Node 0.x:
app.get('/getComments/:userId', function(req, res){
var userId = req.params.userId;
commentCache.get(userId, function(err, data) {
if(err) {
instrumentation.log(err);
return res.json(err);
}
if(data) return res.json(data);
db.getCommentsByUserId(userId, function(err, data) {
if(err) {
instrumentation.log(err);
return res.status(500).end(err);
}
cache.store(data, function() {});
return res.json(data);
});
});
});
So – how do we develop with Node 7?
Node 0.x:
app.get('/getComments/:userId', function(req, res){
var userId = req.params.userId;
commentCache.get(userId, function(err, data) {
if(err) {
instrumentation.log(err);
return res.json(err);
}
if(data) return res.json(data);
db.getCommentsByUserId(userId, function(err, data) {
if(err) {
instrumentation.log(err);
return res.status(500).end(err);
}
cache.store(data, function() {});
return res.json(data);
});
});
});
So – how do we develop with Node 7?
Node 0.x:
app.get('/getComments/:userId', function(req, res){
var userId = req.params.userId;
commentCache.get(userId, function(err, data) {
if(err) {
instrumentation.log(err);
return res.json(err);
}
if(data) return res.json(data);
db.getCommentsByUserId(userId, function(err, data) {
if(err) {
instrumentation.log(err);
return res.status(500).end(err);
}
cache.store(data, function() {});
return res.json(data);
});
});
});
So – how do we develop with Node 7?
Node 0.x:
db.getCommentsByUserId(userId, function(err, data) {
if(err) {
instrumentation.log(err);
return res.status(500).end(err);
}
cache.store(data, function() {});
return res.json(data);
});
});
So – how do we develop with Node 7?
app.get('/getComments/:userId', ({params: {userId}}, res) => {
const fromCache = await commentCache.get(userId);
if(fromCache) return res.json(fromCache);
const fromDb = await db.getCommentsByUserId(userId);
res.json(fromDb);
commentCache.store(userId, fromDb);
});
How our flow has changed: tests
Old
it("does something", function(done) {
myApi("someData", function(err, result) {
assert.equal(err, null);
assert.equal(result === 3);
done();
});
});
New
it("does something", async () => {
assert.equal(await myApi("someData", 3));
});
How our flow has changed: classes
Old
function User(id) {
this.id = id;
}
User.prototype.foo = function(id){
doBar(id);
}
New
class User {
constructor(id) { this.id = id }
foo() { doBar(id); }
}
How our development flow changed.
• Hot reload servers in JS
• Node first approaches in client side flows
• The rise of universal JS
How our web flow changed.
• Rest vs. GraphQL/Falcor.
• Native debugger.
• Handling request/response cycles.
• How express changed.
• How clustering changed.
How production changed.
• The rise of containers.
• More people into node.
• Community got a lot bigger, a lot more mature.
• Node backed by major companies.
• Node for IoT, node on Chakra.
What’s coming next?
Async Iterators
async function* map(fn) {
// async + generator, great stream processing
for await(const value of this) yield fn(value);
};
Observables
Core API Promises
node –expose-wasm
ES Modules
import {some, other} from "module name"
libuv.js
Lower level NodeJS
Code?
Just a few words about open
source
You don’t have to be an expert
We’ll onboard you
Node is actively looking…
benjamingr@gmail.com
Questions?
The Past
The Present
The Future
Thank You

Modern server side development with node.js - Benjamin gruenbaum

  • 1.
    Modern Server Side Developmentwith NodeJS What changed since the 0.10 days Benjamin Gruenbaum
  • 2.
    Benjamin Gruenbaum • Iwork @ TipRanks • NodeJS core collaborator. • Promises guy, bluebird fan and core contributor. • I argue with people online. • StackOverflow guy.
  • 3.
    This talk isin 3 parts The Past The Present The Future
  • 4.
  • 5.
  • 6.
    JavaScript on theserver is an old idea Netscape Enterprise Server – 1995 Steve Yegge’s Server – 2008
  • 7.
    JavaScript on theserver is a good idea? Remember, 2008- JavaScript engines are painfully slow. APIs were nonexistent. Language was hated.
  • 8.
    Suddenly – V8 Googleneeded fast JavaScript in Chrome – so JavaScript engines became fast.
  • 9.
    This Ryan guythought… let’s make a non-blocking server. As in – no thread “block”s in the user server code.
  • 10.
    What can wewrite this in? We need a language that doesn’t have file/net APIs yet to get a sane ecosystem.
  • 11.
    JavaScript has noblocking APIs
  • 12.
    The Result – solving“The 10K Problem”
  • 13.
    How: The EventLoop Threads and OS non-blocking APIs push things into queues User code runs on a single thread and executes handlers on the queues
  • 14.
    Why even writenode? It’s fast enough.
  • 15.
    Why even writenode? Server and client in one language
  • 16.
    Why even writenode? It was cool Remember: in 2009 JS is all the hotness
  • 17.
    Code Sample: ChatServer net.createServer(function(socket) { var user = users.add(socket) socket.on('data', function(data) { <- Callback user.sendOthers("> " + data) }); socket.on('close', function(hadError) { <- Callback user.leave(); }); }).listen(8000);
  • 18.
    Ryan joined Joyent,which looked over Node
  • 19.
    Initially, things workedwell – Node got traction
  • 20.
    But… Stagnation started. Nonew ES features, even when available in Chrome.
  • 21.
    Fast Forward tolast year
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
    Eventually, io.js won.The projects merged.
  • 28.
    The result ofthe io.js fork: Modern V8 version. NodeJS on top of the io.js fork rather than the Joyent repo. Handing over of the Joyent repo to the NodeJS foundation. Community governance. Lots of new features for the community.
  • 29.
    Just how differentis Node today?
  • 30.
    Current version: Node7+ Node 0.12 – last year function persistCriticalFile(cb) { fs.readFile("criticalFile", function(err, data) { if(err) return cb(err); db.persist("collection", process(data), function(err, result) { if(err) return cb(err); cb(null, result); }); }); }
  • 31.
    Current version: Node7+ Node 7 – this year async function persistCriticalFile(cb) { const data = await fs.readFileAsync("criticalFile"); return await db.persistAsync("collection", process(data)); }
  • 32.
    So – howdo we develop with Node 7? Let’s look at a simple scenario. You want to get the comments to a post on your site. - First, from the cache if they’re there. - If they’re not, from the database.
  • 33.
    So – howdo we develop with Node 7? Node 0.x: app.get('/getComments/:userId', function(req, res){ var userId = req.params.userId; commentCache.get(userId, function(err, data) { if(err) { instrumentation.log(err); return res.json(err); } if(data) return res.json(data); db.getCommentsByUserId(userId, function(err, data) { if(err) { instrumentation.log(err); return res.status(500).end(err); } cache.store(data, function() {}); return res.json(data); }); }); });
  • 34.
    So – howdo we develop with Node 7? Node 0.x: app.get('/getComments/:userId', function(req, res){ var userId = req.params.userId; commentCache.get(userId, function(err, data) { if(err) { instrumentation.log(err); return res.json(err); } if(data) return res.json(data); db.getCommentsByUserId(userId, function(err, data) { if(err) { instrumentation.log(err); return res.status(500).end(err); } cache.store(data, function() {}); return res.json(data); }); }); });
  • 35.
    So – howdo we develop with Node 7? Node 0.x: app.get('/getComments/:userId', function(req, res){ var userId = req.params.userId; commentCache.get(userId, function(err, data) { if(err) { instrumentation.log(err); return res.json(err); } if(data) return res.json(data); db.getCommentsByUserId(userId, function(err, data) { if(err) { instrumentation.log(err); return res.status(500).end(err); } cache.store(data, function() {}); return res.json(data); }); }); });
  • 36.
    So – howdo we develop with Node 7? Node 0.x: app.get('/getComments/:userId', function(req, res){ var userId = req.params.userId; commentCache.get(userId, function(err, data) { if(err) { instrumentation.log(err); return res.json(err); } if(data) return res.json(data); db.getCommentsByUserId(userId, function(err, data) { if(err) { instrumentation.log(err); return res.status(500).end(err); } cache.store(data, function() {}); return res.json(data); }); }); });
  • 37.
    So – howdo we develop with Node 7? Node 0.x: db.getCommentsByUserId(userId, function(err, data) { if(err) { instrumentation.log(err); return res.status(500).end(err); } cache.store(data, function() {}); return res.json(data); }); });
  • 38.
    So – howdo we develop with Node 7? app.get('/getComments/:userId', ({params: {userId}}, res) => { const fromCache = await commentCache.get(userId); if(fromCache) return res.json(fromCache); const fromDb = await db.getCommentsByUserId(userId); res.json(fromDb); commentCache.store(userId, fromDb); });
  • 39.
    How our flowhas changed: tests Old it("does something", function(done) { myApi("someData", function(err, result) { assert.equal(err, null); assert.equal(result === 3); done(); }); }); New it("does something", async () => { assert.equal(await myApi("someData", 3)); });
  • 40.
    How our flowhas changed: classes Old function User(id) { this.id = id; } User.prototype.foo = function(id){ doBar(id); } New class User { constructor(id) { this.id = id } foo() { doBar(id); } }
  • 41.
    How our developmentflow changed. • Hot reload servers in JS • Node first approaches in client side flows • The rise of universal JS
  • 42.
    How our webflow changed. • Rest vs. GraphQL/Falcor. • Native debugger. • Handling request/response cycles. • How express changed. • How clustering changed.
  • 43.
    How production changed. •The rise of containers. • More people into node. • Community got a lot bigger, a lot more mature. • Node backed by major companies. • Node for IoT, node on Chakra.
  • 44.
  • 45.
    Async Iterators async function*map(fn) { // async + generator, great stream processing for await(const value of this) yield fn(value); };
  • 46.
  • 47.
  • 48.
  • 49.
    ES Modules import {some,other} from "module name"
  • 50.
  • 51.
  • 52.
    Just a fewwords about open source You don’t have to be an expert We’ll onboard you
  • 53.
    Node is activelylooking… benjamingr@gmail.com
  • 54.
  • 55.