Node
Javascript on the Server
- Javascript runtime built on Chrome's V8 Javascript engine (now also Edge's Chakra)
- uses an event-driven, non-blocking I/O model
- package ecosystem, npm, is the largest ecosystem of open source libraries in the world.
- enables same language on client and server (YAY!)
Atwood's Law
"Any application that can be written in Javascript, will eventually be written in Javascript."
--Jeff Atwood, 2007
- Browser
- Server
- Desktop (electron, Microsoft apps)
- Mobile (hybrid apps, etc)
- CLI (command line interface)
- IoT (internet of things)
Javascript now exists everywhere:
NPM is the biggest
package manager by far in all the history of package managers
Good
- Networking applications with a lot of connections
- Non-blocking IO means multiple requests can be handled on a single thread
Bad
- CPU intensive calculations
- Because it is still just javascript, a high level language with garbage collection, etc
Node Performance
Node is single-threaded
Event-driven programming is a programming paradigm in which the flow of the program is determined by events such as
- user actions (mouse clicks, key presses),
- sensor outputs, or
- messages from other programs/threads.
Scaling Node
If node is single-threaded, you might be wondering how to take advantage of multiple core architectures.
Scalability in Node is not an afterthought. It’s something that’s baked into the core of the runtime.
Node is named Node to emphasize the idea that a Node application should comprise multiple small distributed nodes that communicate with each other.
separating by data (e.g. by region)
Cloning / Clustering / Load Balancing
using node's built-in cluster module.
separating by function
Decomposing / Microservices
Splitting / Horizontal Partitioning / Sharding
Node Scaling Strategies
If you are lucky enough that your app needs to scale, you may eventually need all three:
Blocking
Non-blocking
const fs = require('fs')
// blocks here until file is read
const data = fs.readFileSync('/file.md')
const fs = require('fs')
fs.readFile('/file.md', (err, data) => {
if (err) throw err
})
const util = require('util')
const fs = require('fs')
const readFile
= util.promisify(fs.readFile)
readFile('/file.md')
.then((data) => {
// Do something with `data`
})
.catch((error) => {
// Handle the error.
})
via callback (traditional)
Non-blocking
via promise (new)
traditional syntax
future syntax
Modules
module.exports = {
myModule: 'hello world'
}
export const myModule = 'hello world'
my-module.js
my-module.mjs
const myModule
= require('./my-module').myModule
console.log(myModule)
parent.js
import { myModule } from './my-module'
console.log(myModule)
parent.mjs
Packages
- Has a package.json file to specify package metadata and dependencies on other packages
- May contain 1 or more modules
- May be published on npm
- May be consumed as a dependency by other projects
The leftpad problem
module.exports = leftpad;
function leftpad (str, len, ch) {
str = String(str);
var i = -1;
if (!ch && ch !== 0) ch = ' ';
len = len - str.length;
while (++i < len) {
str = ch + str;
}
return str;
}
NPM makes it easy to both consume and produce TINY packages. And that can potentially "break the internet"
Are tiny packages bad?
Short answer: NO!
Code reuse and reducing
cognitive load for developers is a very good thing.
However, there are some caveats:
- Security
- Third party deps can break in the future
- Potentially some tiny perf overhead
- You forget how to be a "real programmer" (just kidding! lol)
Node
By Jason Sewell
Node
- 1,288