Node+Hero+-+The+complete+Node js+tutorial+series+from+RisingStack
Node+Hero+-+The+complete+Node js+tutorial+series+from+RisingStack
Get started with Node.js and deliver software products using it.
RisingStack
Table of contents
RisingStack
03
USING NPM
08
12
17
USING DATABASES
22
28
PROJECT STRUCTURING
32
35
UNIT TESTING
40
DEBUGGING
46
SECURITY
50
55
60
Node.js in a Nutshell
RisingStack
If everything is ok, it will return the version number of the currently active
Node.js binary.
Then you can switch to Node.js v5 with the very same command:
nvm use 5
RisingStack
Hello World
To get started with Node.js, lets try it in the terminal! Start Node.js by
simply typing node:
$ node
>
Once you hit Enter, you will get something like this:
> console.log(hello from Node.js)
hello from Node.js
undefined
Feel free to play with Node.js by using this interface - I usually try out
small snippets here if I dont want to put them into a file.
To run this file, you should open up your terminal again and navigate
to the directory in which you placed index.js.
Once you successfully navigated yourself to the right spot, run your
file using thenode index.js command. You can see that it will
produce the same output as before - printing the string directly into
the terminal.
RisingStack
Code - you name it) and create the following directory structure
(with empty files), but leave the package.json out for now, we will
generate it automatically in the next step:
|
|
app
calc.js
index.js
index.js
package.json
Its a good practice to add a start script to your package.jsononce you do that as shown in the example above you can start your
application with the npm start command as well. It comes really
handy when you want to deploy your application to a PaaS provider they can recognize it and start your application using that.
Now lets head back to the first file you created called index.js.
I recommend to keep the this file very thin - only requiring the application
itself (the index.js file from the /app subdirectory you created before).
Copy the following script into your index.js file and hit save to do this:
// index.js
require(./app/index)
RisingStack
Now it is time to start building the actual application. Open the index.
js file from the /app folder to create a very simple example: adding an
array of numbers. In this case the index.js file will only contain the
numbers we want to add, and the logic that does the calculation needs
to be placed in a separate module.
Paste this script to the index.js file in your /app directory.
// app/index.js
const calc = require(./calc)
const numbersToAdd = [
3,
4,
10,
2
]
const result = calc.sum(numbersToAdd)
console.log(`The result is: ${result}`)
Now paste the actual business logic into the calc.js file that can be
found in the same folder.
// app/calc.js
function sum (arr) {
return arr.reduce(function(a, b) {
return a + b
}, 0)
}
module.exports.sum = sum
To check if youd succeeded, save these files, open up terminal and enter
npm start or node index.js. If you did everything right, you will get
back the answer: 19. If something went wrong, review the console log
carefully and find the issue based on that.
In our next chapter called Using NPM we are going to take a look on
how to use NPM, the package manager for JavaScript.
RisingStack
USING NPM
In this chapter, youll learn what NPM is and how to use it. Lets get
started!
NPM in a Nutshell
NPM is the package manager used by Node.js applications - you can
find a ton of modules here, so you dont have to reinvent the wheel. It
is like Maven for Java or Composer for PHP. There are two primary
interfaces you will interact with - the NPM website and the NPM
command line toolkit.
Both the website and the CLI uses the same registry to show modules
and search for them.
The Website
The NPM website can be found at https://npmjs.com. Here you can
sign up as a new user or search for packages.
Note, that NPM is bundled with the Node.js binary, so you dont have to
install it - however, if you want to use a specific npm version, you can
update it. If you want to install npm version 3, you can do that with:
npm install npm@3 -g.
RisingStack
Adding Dependencies
In this section you are going to learn how to add runtime
dependencies to your application.
Once you have your package.json file you can add dependencies to
your application. Lets add one! Try the following:
npm install lodash --save
With this single command we achieved two things: first of all, lodash
is downloaded and placed into the node_modules folder. This is the
folder where all your external dependencies will be put. Usually, you
dont want to add this folder to your source control, so if you are using
git make sure to add it to the .gitignore file.
This can be a good starting point for your .gitignore [Click here for
the GitHub link]
This means that lodash with version 4.6.1 is now installed and ready
to be used. Note, that NPM follows SemVer to version packages.
Given a version number MAJOR.MINOR.PATCH, increment the MAJOR
version when you make incompatible API changes, MINOR version
when you add functionality in a backwards-compatible manner, and
PATCH version when you make backwards-compatible bug fixes. For
more information: http://semver.org/
As lodash is ready to be used, lets see how we can do so! You can
RisingStack
do it in the same way you did it with your own module except now you
dont have to define the path, only the name of the module:
// index.js
const _ = require(lodash)
_.assign({ a: 1 }, { b: 2 }, { c: 3 });
// { a: 1, b: 2, c: 3 }
NPM Scripts
NPM script is a very powerful concept - with the help of them you can
build small utilities or even compose complex build systems.
The most common ones are the start and the test scripts. With the
start you can define how one should start your application, while
test is for running tests. In your package.json they can look
something like this:
scripts: {
start: node index.js,
test: mocha test,
your-custom-script: echo npm
}
RisingStack
10
You can install scoped packages the same way as you did before:
npm install @myorg/mypackage --save-dev
In the next chapter, you can learn the principles of async programming
using callbacks and Promises.
RisingStack
11
UNDERSTANDING ASYNC
PROGRAMMING
In this chapter, Ill guide you through async programming principles,
and show you how to do async in JavaScript and Node.js.
Synchronous Programming
In traditional programming practice, most I/O operations happen
synchronously. If you think about Java, and about how you would read
a file using Java, you would end up with something like thiS:
try(FileInputStream inputStream = new
FileInputStream(foo.txt)) {
Session IOUtils;
String fileContent = IOUtils.toString(inputStream);
}
If you have more blocking operations, the event queue gets even
worse:
(The red bars show when the process is waiting for an external
resources response and is blocked, the black bars show when your
code is running, the green bars show the rest of the application)
To resolve this issue, Node.js introduced an asynchronous
programming model.
RisingStack
12
What did just happen here? We tried to read a file using the
synchronous interface of the fs module. It works as expected - the
content variable will contain the content of file.md. The problem
with this approach is that Node.js will be blocked until the operation is
finished - meaning it can do absolutely nothing while the file is being
read.
Lets see how we can fix it!
Asynchronous programming - as we know now in JavaScript - can only
be achieved with functions being first-class citizens of the language:
they can be passed around like any other variables to other functions.
Functions that can take other functions as arguments are called
higher-order functions.
One of the easiest example for higher order functions:
const numbers = [2,4,1,5,4]
function isBiggerThanTwo (num) {
return num > 2
}
numbers.filter(isBiggerThanTwo)
RisingStack
13
As you can see once we started to read our file the execution
continued, and the application printed end of the file. Our callback
was only called once the file read was finished. How is it possible?
Meet the event loop.
RisingStack
14
RisingStack
15
Async.js
To avoid the so-called Callback-Hell one thing you can do is to start
using async.js.
Async.js helps to structure your applications and makes control flow
easier.
Lets check a short example of using Async.js, and then rewrite it by
using Promises.
The following snippet maps through three files for stats on them:
async.parallel([file1, file2, file3], fs.stat,
function (err, results) {
// results is now an array of stats for each file
})
Promises
The Promise object is used for deferred and asynchronous
computations. A Promise represents an operation that hasnt
completed yet but is expected in the future.
In practice, the previous example could be rewritten as follows:
function stats (file) {
return new Promise((resolve, reject) => {
fs.stat(file, (err, data) => {
if (err) {
return reject (err)
}
resolve(data)
})
})
}
Promise.all([
stats(file1),
stats(file2),
stats(file3)
])
.then((data) => console.log(data))
.catch((err) => console.log(err))
Of course, if you use a method that has a Promise interface, then the
Promise example can be a lot less in line count as well.
In the next chapter, you will learn how to fire up your first Node.js
HTTP server.
RisingStack
16
17
Express
Fast, unopinionated, minimalist web framework for Node.js - http://
expressjs.com/
Adding Express to your project is only an NPM install away:
$ npm install express --save
Once you have Express installed, lets see how you can create a similar
application as before:
const express = require(express)
const app = express()
const port = 3000
app.get(/, (request, response) => {
response.send(Hello from Express!)
})
app.listen(port, (err) => {
if (err) {
return console.log(something bad happened, err)
}
console.log(`server is listening on ${port}`)
})
The biggest difference what you have to notice here is that Express
by default gives you a router. You dont have to check manually for
the URL to decide what to do, but instead, you define the applications
routing with app.get, app.post, app.put, etc. They are translated
to the corresponding HTTP verbs.
One of the most powerful concepts that Express implements is the
middleware pattern.
Middlewares
You can think of middlewares as Unix pipelines, but for HTTP requests.
In the diagram you can see how a request can go through an Express
application. It travels to three middlewares. Each can modify it, then
based on the business logic either the third middleware can send back
a response or it can be a route handler.
RisingStack
18
Error handling
As in all frameworks, getting the error handling right is crucial. In
Express you have to create a special middleware function to do so - a
middleware with four parameters:
const express = require(express)
const app = express()
app.get(/, (request, response) => {
throw new Error(oops)
})
app.use((err, request, response, next) => {
// log the error, for now just console.log
console.log(err)
response.status(500).send(Something broke!)
})
RisingStack
19
Rendering HTML
So far we have taken a look on how to send JSON responses - it is
time to learn how to render HTML the easy way. For that, we are going
to use the handlebars package with the express-handlebars wrapper.
First, lets create the following directory structure:
index.js
views
home.hbs
layouts
main.hbs
Once you have that, populate index.js with the following snippet:
// index.js
const path = require(path)
const express = require(express)
const exphbs = require(express-handlebars)
app.engine(.hbs, exphbs({
defaultLayout: main,
extname: .hbs,
layoutsDir: path.join(__dirname, views/layouts)
}))
app.set(view engine, .hbs)
app.set(views, path.join(__dirname, views))
The code above initializes the handlebars engine and sets the layouts
directory to views/layouts. This is the directory where your layouts will
be stored.
Once you have this setup, you can put your initial html into the main.hbs
- to keep things simple lets go with this one:
<html>
<head>
<title>Express handlebars</title>
</head>
<body>
{{{body}}}
</body>
</html>
RisingStack
20
This is just the tip of the iceberg - to learn how to add more layouts
and even partials, please refer to the official express-handlebars
documentation.
Debugging Express
In some cases, you may need to see what happens with Express when
your application is running. To do so, you can pass the following
environment variable to Express: DEBUG=express*.
You have to start your Node.js HTTP server using:
$ DEBUG=express* node index.js
Summary
This is how can you set up your first Node.js HTTP server from scratch.
I recommend Express to begin with, then feel free to experiment. Let
me know how did it go in the comments.
In the next chapter, you will learn how to retrieve information from
databases.
RisingStack
21
USING DATABASES
In the following Node.js database chapter, Ill show you how you can
set up a Node.js application with a database, and teach you the basics
of using it.
This way you can store the users in a global variable, which will reside
in memory for the lifetime of your application.
Using this method might be problematic for several reasons:
RAM is expensive,
memory resets each time you restart your application,
if you dont clean up, sometimes youll end up with stack overflow.
RisingStack
22
This way we wont lose user data, not even after a server reset. This
solution is also cost efficient, since buying storage is cheaper than
buying RAM.
Unfortunately storing user data this way still has a couple of flaws:
Appending is okay, but think about updating or deleting.
If were working with files, there is no easy way to access them in
parallel (system-wide locks will prevent you from writing).
When we try to scale our application up, we cannot split files (you
can, but it is way beyond the level of this tutorial) in between servers.
This is where real databases come into play.
You might have already heard that there are two main kinds of
databases: SQL and NoSQL.
SQL
Lets start with SQL. It is a query language designed to work with
relational databases. SQL has a couple of flavors depending on the
product youre using, but the fundamentals are same in each of them.
The data itself will be stored in tables, and each inserted piece will
be represented as a row in the table, just like in Google Sheets, or
Microsoft Excel.
Within an SQL database, you can define schemas - these schemas
will provide a skeleton for the data youll put in there. The types of
the different values have to be set before you can store your data. For
example, youll have to define a table for your user data, and have to
tell the database that it has a username which is a string, and age,
which is an integer type.
RisingStack
23
NoSQL
On the other hand, NoSQL databases have become quite popular
in the last decade. With NoSQL you dont have to define a schema
and you can store any arbitrary JSON. This is handy with JavaScript
because we can turn any object into a JSON pretty easily. Be careful,
because you can never guarantee that the data is consistent, and you
can never know what is in the database.
For further information read this excellent guide on getting your first
database up and running.
RisingStack
24
Finally, we can get back to coding. Here is how you can interact with
your database via your Node.js program.
use strict
const pg = require(pg)
const conString = postgres://username:password@
localhost/node_hero // make sure to match your own
databases credentials
pg.connect(conString, function (err, client, done) {
if (err) {
return console.error(error fetching client from
pool, err)
}
client.query(SELECT $1::varchar AS my_first_query,
[node hero], function (err, result) {
done()
if (err) {
return console.error(error happened during
query, err)
}
console.log(result.rows[0])
process.exit(0)
})
})
25
RisingStack
26
Try things out and experiment, because thats the best way of
becoming a real Node Hero! Practice and be prepared for the next
chapter on how to communicate with third-party APIs!
RisingStack
27
Whats HTTP?
HTTP stands for Hypertext Transfer Protocol. HTTP functions as a
requestresponse protocol in the clientserver computing model.
RisingStack
28
request(options)
.then(function (response) {
// Request was successful, use the response object
at will
})
.catch(function (err) {
// Something bad happened, handle the error
})
If you are calling a JSON API, you may want the request-promise to
parse the response automatically. In this case, just add this to the
request options:
json: true
RisingStack
29
request(options)
.then(function (response) {
// Handle the response
})
.catch(function (err) {
// Deal with the error
})
To add query string parameters you just have to add the qs property
to the options object:
const options = {
method: GET,
uri: https://risingstack.com,
qs: {
limit: 10,
skip: 20,
sort: asc
}
}
Error handling
Error handling is an essential part of making requests to external APIs,
as we can never be sure what will happen to them. Apart from our
client errors the server may respond with an error or just send data
in a wrong or inconsistent format. Keep these in mind when you try
handling the response. Also, using catch for every request is a good
way to avoid the external service crashing our server.
RisingStack
30
Putting it together
As you have already learned how to spin up a Node.js HTTP server,
how to render HTML pages, and how to get data from external APIs, it
is time to put them together!
In this example, we are going to create a small Express application
that can render the current weather conditions based oncity names.
(To get your AccuWeatherAPI key, please visit their developer site)
const express = require(express)
const rp = require(request-promise)
const exphbs = require(express-handlebars)
const app = express()
app.engine(.hbs, exphbs({
defaultLayout: main,
extname: .hbs,
layoutsDir: path.join(__dirname, views/layouts)
}))
app.set(view engine, .hbs)
app.set(views, path.join(__dirname, views))
app.get(/:city, (req, res) => {
rp({
uri: http://apidev.accuweather.com/locations/v1/
search,
qs: {
q: req.params.city,
apiKey: api-key
// Use your accuweather API key here
},
json: true
})
.then((data) => {
res.render(index, data)
})
.catch((err) => {
console.log(err)
res.render(error)
})
})
app.listen(3000)
RisingStack
31
PROJECT STRUCTURING
Most Node.js frameworks dont come with a fixed directory structure
and it might be challenging to get it right from the beginning. In this
chapter, you will learn how to properly structure a Node.js project to
avoid confusion when your applications start to grow.
Rule 1:
Organize your Files Around Features, Not Roles
Imagine, that you have the following directory structure:
// DONT
.
controllers
|
product.js
|
user.js
models
|
product.js
|
user.js
views
|
product.hbs
|
user.hbs
RisingStack
32
Rule 3:
Place Your Test Files Next to The Implementation
Tests are not just for checking whether a module produces the
expected output, they also document your modules (you will learn
more on testing in the upcoming chapters). Because of this, it is easier
to understand if test files are placed next to the implementation.
Put your additional test files to a separate test folder to avoid
confusion.
.
|
|
|
|
|
|
|
|
RisingStack
test
setup.spec.js
product
index.js
product.js
product.spec.js
product.hbs
user
index.js
user.js
user.spec.js
user.hbs
33
|
|
|
|
|
|
config
index.js
server.js
product
index.js
product.js
product.spec.js
product.hbs
Rule 5:
Put Your Long npm Scripts in a scripts Directory
Create a separate directory for your additional long scripts in
package.json
.
|
|
|
|
|
|
scripts
syncDb.sh
provision.sh
product
index.js
product.js
product.spec.js
product.hbs
In the next chapter of Node Hero, you are going to learn how to
authenticate users using Passport.js.
RisingStack
34
Technologies to use
Before jumping into the actual coding, lets take a look at the new
technologies we are going to use in this chapter.
What is Passport.js?
Simple, unobtrusive authentication for Node.js - passportjs.org
What is Redis?
Redis is an open source (BSD licensed), in-memory data structure
store, used as database, cache and message broker. - redis.io
We are going to store our users session information in Redis, and not
in the processs memory. This way our application will be a lot easier
to scale.
RisingStack
35
|
|
|
|
|
app
authentication
note
user
index.js
layout.hbs
config
index.js
index.js
package.json
As you can see we will organize files and directories around features.
We will have a user page, a note page, and some authentication
related functionality.
(Download the full source code at https://github.com/RisingStack/
nodehero-authentication)
RisingStack
36
RisingStack
37
// file:app/authenticate/init.js
const passport = require(passport)
const LocalStrategy = require(passport-local).Strategy
const user = {
username: test-user,
password: test-password,
id: 1
}
passport.use(new LocalStrategy(
function(username, password, done) {
findUser(username, function (err, user) {
if (err) {
return done(err)
}
if (!user) {
return done(null, false)
}
if (password !== user.password ) {
return done(null, false)
}
return done(null, user)
})
}
))
Once the findUser returns with our user object the only thing left is to
compare the user-fed and the real password to see if there is a match.
If it is a match, we let the user in (by returning the user to passport
- return done(null, user)), if not we return an unauthorized
error (by returning nothing to passport - return done(null)).
It only has one role if the user is authenticated (has the right cookies)
it simply calls the next middleware; otherwise it redirects to the page
where the user can log in.
RisingStack
38
Summary
In this Node.js tutorial, you have learned how to add basic
authentication to your application. Later on, you can extend it with
different authentication strategies, like Facebook or Twitter. You can
find more strategies at http://passportjs.org/.
The full, working example is on GitHub, you can take a look here:
https://github.com/RisingStack/nodehero-authentication
The next chapter of Node Hero will be all about unit testing Node.js
applications. You will learn concepts like unit testing, test pyramid,
test doubles and a lot more!
RisingStack
39
UNIT TESTING
In this chapter, you are going to learn what is unit testing in Node.js,
and how to test your applications properly.
You may ask: what should I test in my application? How many tests
should I have?
The answer varies across use-cases, but as a rule of thumb, you can
follow the guidelines set by the test pyramid.
Essentially, the test pyramid describes that you should write unit tests,
integration tests and end-to-end tests as well. You should have more
integration tests than end-to-end tests, and even more unit tests.
Lets take a look at how you can add unit tests for your applications!
Please note, that we are not going to talk about integration tests and
end-to-end tests here as they are far beyond the scope of this tutorial.
RisingStack
40
RisingStack
41
Stubs
Stubs are like spies, but they replace the target function. You can
use stubs to control a methods behaviour to force a code path (like
throwing errors) or to prevent calls to external resources (like HTTP
APIs).
it(calls all subscribers, even if there are
exceptions, function (){
var message = an example message
var error = an example error message
var stub = sinon.stub().throws()
var spy1 = sinon.spy()
var spy2 = sinon.spy()
PubSub.subscribe(message, stub)
PubSub.subscribe(message, spy1)
PubSub.subscribe(message, spy2)
PubSub.publishSync(message, undefined)
assert(spy1.called)
assert(spy2.called)
assert(stub.calledBefore(spy1))
})
// example taken from the sinon documentation site:
http://sinonjs.org/docs/
Mocks
A mock is a fake method with a pre-programmed behavior and
expectations.
it(calls all subscribers when exceptions happen,
function () {
var myAPI = {
method: function () {}
}
var spy = sinon.spy()
var mock = sinon.mock(myAPI)
mock.expects(method).once().throws()
PubSub.subscribe(message, myAPI.method)
PubSub.subscribe(message, spy)
PubSub.publishSync(message, undefined)
mock.verify()
assert(spy.calledOnce)
// example taken from the sinon documentation site:
http://sinonjs.org/docs/
})
As you can see, for mocks you have to define the expectations upfront.
RisingStack
42
This module does one thing: it saves a web page (based on the given
URL) to a file on the local machine. To test this module we have to
stub out both the fs module as well as the request module.
Before actually starting to write the unit tests for this module, at
RisingStack, we usually add a test-setup.spec.js file to do
basics test setup, like creating sinon sandboxes. This saves you
from writing sinon.sandbox.create() and sinon.sandbox.
restore() after each tests.
// test-setup.spec.js
const sinon = require(sinon)
const chai = require(chai)
beforeEach(function () {
this.sandbox = sinon.sandbox.create()
})
afterEach(function () {
this.sandbox.restore()
})
RisingStack
43
Also, please note, that we always put test files next to the
implementation, hence the .spec.js name. In our package.json
you can find these lines:
{
test-unit: NODE_ENV=test mocha /**/*.spec.js,
}
Code coverage
To get a better idea of how well your codebase is covered with tests,
you can generate a coverage report.
This report will include metrics on:
line coverage,
statement coverage,
branch coverage,
and function coverage.
RisingStack
44
You can click around, and actually see your source code annotated
- which part is tested, which part is not.
RisingStack
45
DEBUGGING
In this chapter, you are going to learn debugging your Node.js
applications using the debug module, the built-in Node debugger and
Chromes developer tools.
Bugs, debugging
The term bug and debugging have been a part of engineering jargon
for many decades. One of the first written mentions of bugs is as
follows:
It has been just so in all of my inventions. The first step is an intuition,
and comes with a burst, then difficulties arise this thing gives out and
[it is] then that Bugs as such little faults and difficulties are called
show themselves and months of intense watching, study and labor are
requisite before commercial success or failure is certainly reached.
Thomas Edison
RisingStack
46
To use the debug module, you have to set the DEBUG environment
variable when starting your applications. You can also use the *
character to wildcard names. The following line will print all the
express related logs to the standard output.
DEBUG=express* node app.js
Once you have done that, you will see something like this:
RisingStack
47
Watchers
It is possible to watch expression and variable values during debugging.
On every breakpoint, each expression from the watchers list will be
evaluated in the current context and displayed immediately before the
breakpoints source code listing.
To start using watchers, you have to define them for the expressions
you want to watch. To do so, you have to do it this way:
watch(expression)
RisingStack
48
Good news, the Chrome debug protocol is already ported into a Node.
js module and can be used to debug Node.js applications.
To start using it, you have to install node-inspector first:
npm install -g node-inspector
Once you installed it, you can start debugging your applications by
starting them this way:
node-debug index.js --debug-brk
In the next chapter of Node Hero, you are going to learn how to secure
your Node.js applications.
RisingStack
49
SECURITY
In this Node.js security chapter, you are going to learn how to defend
your applications against the most common attack vectors.
RisingStack
50
use strict
delete Object.prototype
// TypeError
var obj = {
a: 1,
a: 2
}
// syntax error
RisingStack
51
RisingStack
52
In Node.js you can easily create this cookie using the cookies
package. Again, this is quite low-level, so you will probably end up
using a wrapper, like the cookie-session.
var cookieSession = require(cookie-session)
var express = require(express)
var app = express()
app.use(cookieSession({
name: session,
keys: [
process.env.COOKIE_KEY1,
process.env.COOKIE_KEY2
]
}))
app.use(function (req, res, next) {
var n = req.session.views || 0
req.session.views = n++
res.end(n + views)
})
app.listen(3000)
Tools to Use
Congrats, youre almost there! If you followed this tutorial and did
the previous steps thoroughly, you have just one area left to cover
regarding Node.js security. Lets dive into using the proper tools to
look for module vulnerabilities!
Rule 9: Look for vulnerabilities with Retire.js
The goal of Retire.js is to help you detect the use of module versions
with known vulnerabilities.
Simply install with:
npm install -g retire
After that, running it with the retire command is going to look for
vulnerabilities in your node_modules directory. (Also note, that retire.
js works not only with node modules but with front end libraries as
well.)
RisingStack
53
Rule 10: Audit your modules with the Node Security Platform CLI
nsp is the main command line interface to the Node Security Platform.
It allows for auditing a package.json or npm-shrinkwrap.json
file against the NSP API to check for vulnerable modules.
npm install nsp --global
# From inside your project directory
nsp check
Node.js security is not a big deal after all is it? I hope you found these
rules to be helpful for securing your Node.js applications - and will
follow them in the future since security is a part of your job!
If youd like to read more on Node.js security, I can recommend these
articles to start with:
Node.js Security Tips
OWASPs Top Ten Cheat Sheet
Node.js security checklist
In the next chapter of Node Hero, you are going to learn how to deploy
your secured Node.js application, so people can actually start using it!
RisingStack
54
RisingStack
55
Deploying to Heroku
Click Create New App, add a new and select a region. In a matter of
seconds, your application will be ready, and the following screen will
welcome you:
Go to the Settings page of the application, and grab the Git URL. In
your terminal, add the Heroku remote url:
git remote add heroku HEROKU_URL
You are ready to deploy your first application to Heroku - it is really just
a git push away:
git push heroku master
RisingStack
56
Once you do this, Heroku starts building your application and deploys
it as well. After the deployment, your service will be reachable at
https://YOUR-APP-NAME.herokuapp.com.
Heroku Add-ons
One of the most valuable part of Heroku is its ecosystem since there
are dozens of partners providing databases, monitoring tools, and
other solutions.
To try out an add-on, install Trace, our Node.js monitoring solution. To
do so, look for Add-ons on your applications page, and start typing
Trace, then click on it to provision. Easy, right?
In this part of the tutorial, you are going to learn how to create images
from your Node.js applications and run them.
RisingStack
57
Docker Basics
To get started with Docker, download and install it from the Docker
website.
RisingStack
58
Once you have the Dockerfile, you can create an image from it using:
docker build .
Using private NPM modules? Check out our tutorial on how to install
private NPM modules in Docker!
After the successful build of your image, you can list them with:
docker images
To run an image:
docker run IMAGE_ID
In the next chapter of Node Hero, you are going to learn how to
monitor your Node.js applications - so that it can be online 24/7.
RisingStack
59
MONITORING NODE.JS
APPLICATIONS
In the last chapter of the series, Im going to show you how to do
Node.js monitoring and how to find advanced issues in production
environments.
RisingStack
60
Server Monitoring
Server monitoring is responsible for the host machine. It should be
able to help you answer the following questions:
Does my server have enough disk space?
Does it have enough CPU time?
Does my server have enough memory?
Can it reach the network?
For server monitoring, you can use tools like zabbix.
Application Monitoring
Application monitoring, on the other hand, is responsible for the health
of a given application instance. It should let you know the answers to
the following questions:
Can an instance reach the database?
How much request does it handle?
What are the response times for the individual instances?
Can my application serve requests? Is it up?
For application monitoring, I recommend using our tool called Trace.
What else? :)
We developed it to be an easy to use and efficient tool that you can
use to monitor and debug applications from the moment you start
building them, up to the point when you have a huge production app
with hundreds of services.
RisingStack
61
Once you registered, follow these steps to add Trace to your Node.js
applications. It only takes up a minute - and these are the steps you
should perform:
Easy, right? If everything went well, you should see that the service you
connected has just started sending data to Trace:
RisingStack
62
You can use the response time panel to check out median and 95th
percentile response data. It helps you to figure out when and why
your application slows down and how it affects your users.
The throughput graph shows request per minutes (rpm) for status
code categories (200-299 // 300-399 // 400-499 // >500 ). This way
you can easily separate healthy and problematic HTTP requests
within your application.
The memory usage graph shows how much memory your process
uses. Its quite useful for recognizing memory leaks and preempting
crashes.
If youd like to see special Node.js metrics, check out the garbage
collection and event loop graphs. Those can help you to hunt down
memory leaks. Read our metrics documentation.
RisingStack
63
With this view, you can easily find memory leaks in your application.
In a previous article weve written about this process in a detailed
way, you can read it here: Hunting a Ghost - Finding a Memory Leak
in Node.js
RisingStack
64
Once you loaded it, youll be able to see the 10 second timeframe of
your application and see all of your functions with times and URLs as
well.
With this data, youll be able to figure out what slows down your
application and deal with it!
The End
This is it.
During the 13 episodes of the Node Hero series, you learned the
basics of building great applications with Node.js.
I hope you enjoyed it and improved a lot! Please share this series with
your friends if you think they need it as well - and show them Trace too.
Its a great tool for Node.js development!
RisingStack
65