''' Node JS tutorial | Modern JS

Node JS tutorial

Node JS -- also known as Node.js -- is practically at the center of all modern JavaScript development. Node JS plays such a critical role in the modern JavaScript ecosystem because it's used to run JavaScript, and not just any JavaScript like the kind browsers run on a day to day basis, but rather more advanced JavaScript (e.g. of the networking and file system type). In addition, Node JS is also designed to administer JavaScript packages, which in turn allow Node JS to run more complex JavaScript applications built on these JavaScript packages.

Before jumping into how Node JS works, let's take a quick look at how Node JS compares to other software you've probably worked with, namely JavaScript browser engines and other programming language run-time environments, in this manner, you'll gain a better understanding of the tasks Node JS is designed to perform.

How Node JS compares to JavaScript browser engines and other programming language run-time environments.

In Modern JavaScript essentials, I mentioned how the various mass-market browsers (e.g. Google Chrome, Microsoft Edge, Firefox, Apple Safari) are equipped with different JavaScript engines to support the execution of JavaScript or more specifically ECMAScript, the last of which is the standard that gives form to the JavaScript language.

All these JavaScript engines are great for running JavaScript on a browser, but you have to remember these JavaScript engines are pegged to ECMAScript standards. So what's the problem with ECMAScript standards ? They tend to be limited in terms of functionalities. Although ECMAScript standards have evolved to support ever increasing features -- as you can review in the previous sections: JavaScript key concepts & syntax, JavaScript data types, JavaScript object-orientated and prototype-based programming, JavaScript for loops and JavaScript asynchronous behavior -- relying solely on ECMAScript standards means the JavaScript language is pretty constrained, particularly if you compare it to other programming languages and their run-time environments.

In most programming languages like Python, PHP or Ruby, when you install their run-time environments, an installation is not only equipped to run the entire set of instructions available in a programming language, it's also equipped with a set of staple libraries/modules to execute run of the mill programming tasks (e.g. read/write files, establish network connections), as well as the ability to leverage third party libraries/modules to execute practically any kind of programming tasks. This type of architecture which is available out-of-the-box in most programming language run-times, is one of the major voids Node JS fills over JavaScript browser engines and is why Node JS is such a dominant player in the modern JavaScript ecosystem.

If you view Node JS from the perspective of other programming language run-time environments, Node JS is like the JavaScript run-time environment that should have been, because it resembles what most programming language run-times offer out-of-the-box. Figure 6-1 illustrates the resemblance of a Node JS installation to a Python installation.

Figure 6-1. Node JS installation vs. Python installation

When you perform a Python installation it comes equipped with the features you see to the right side of figure 6-1. For starters, a Python installation allows the execution of the Python language, but in addition comes equipped with a set of handy Python modules to execute common programming tasks in Python (e.g. read/write files, establish network connections). In addition, a Python installation also comes equipped with a package manager -- named pip -- designed for the installation and management of third party Python packages to aid in the execution of more advanced programming tasks in Python (e.g. web frameworks, business analytics).

On the left side of figure 6-1, you can see that a Node JS installation at its core uses the same V8 JavaScript engine built-in to the Google Chrome browser. So does this mean Node JS is like a browser ? No, Node JS leverages the same V8 JavaScript engine used by a browser to process JavaScript, but this is the only thing Node JS has in common with a browser. In figure 6-1 you can also see a Node JS installation comes equipped with a set of handy JavaScript modules[1] to execute common programming tasks in JavaScript. In addition, a Node JS installation also comes equipped with a package manager -- named npm -- designed for the installation and management of third party JavaScript packages to aid in the execution of more advanced programming tasks in JavaScript (e.g. web frameworks, business analytics).

With this overview of what constitutes a Node JS installation, you can understand why the built-in JavaScript installations of mass-market browsers with their more limited functionalities have never been an option for modern JavaScript development. It required looking beyond the features offered by built-in JavaScript installations of mass-market browsers and getting insight from what other programming languages offered out-of-the-box, for Node JS to come into existence and become a dominant force in modern JavaScript projects.

Node JS - Installation and versioning

Since Node JS is a core piece of software that runs JavaScript, like all other core pieces of software that run programming languages, it's generally very easy to install, but it can have a myriad of behavioral differences if you don't use a specific version for a given JavaScript application.

Node JS has been released in over twelve major versions, with even numbered versions (e.g. 12, 10, 8) representing LTS (Long Term Support) releases -- which means they're maintained for a longer period of time, approximately 30 months -- where as odd numbered versions (e.g. 11, 9, 7) represent quicker EOL (End of Life) releases -- which means as soon as a new version is released, approximately every 6 months, the prior version is no longer updated. The finer details of the Node JS version release strategy[2] can be a little complex to follow, so for practical purposes, I recommend you stick to using Node JS LTS releases or whatever Node JS version the provider of a given JavaScript application recommends.

At the time of this writing, Node JS 12 is the latest LTS release, so any steps outlined from this point on are based on the use of Node JS 12. I can't emphasize enough how using Node JS 12 is no guarantee that it will work on all software that requires Node JS. In fact, from personal experience I can say that sometimes even minor Node JS version variations (e.g. 10.1.0 to 10.8.0) can break software, never mind major Node JS version variations (e.g. 8 to 10 or 10 to 12), so if a piece of JavaScript software recommends using Node JS version x.x, use that Node JS version to avoid any unexpected behaviors.

When it comes to installation, Node JS is available[3] for a wealth of operating systems and processor architectures, in addition to being available in source code so it can be built to run on any platform. In addition, a lot of operating systems support the turn-key installation of Node JS through their package managers (e.g. apt, rpm), albeit this last approach rarely supports the most up to date Node JS version, so it's often best to directly download a specific Node JS installation package instead of relying on an operating system package manager.

In most cases, a few mouse clicks or command line instructions will be sufficient to install Node JS. But in case you get stuck during the installation process, I advise you to look over other resources on the web for a possible solution to your installation problems, as covering Node JS installation problems would go beyond the scope of how Node JS works. Being such a widely adopted platform, it's very likely someone else has encountered and documented a possible solution to a given Node JS installation problem.

Once you successfully install Node JS, it will have a bin folder with the following executables:

To make your life easier, I suggest you add the Node JS bin folder to your operating system's PATH environment variable[4][5] so the Node JS executables node, npm and npx become available anywhere on your operating system.

Node JS node: A JavaScript REPL

The node command is one of three major executables included with Node JS and provides quick access to a JavaScript run-time environment. Go ahead and execute node without any arguments to enter the REPL mode as illustrated in listing 6-1.

Listing 6-1. node REPL mode
[user@laptop]$ node
Welcome to Node.js v12.2.0.
Type ".help" for more information.
> .help
.break    Sometimes you get stuck, this gets you out
.clear    Alias for .break
.editor   Enter editor mode
.exit     Exit the repl
.help     Print this help message
.load     Load JS from a file into the REPL session
.save     Save all evaluated commands in this REPL session to a file

Press ^C to abort current expression, ^D to exit the repl
>

When you execute node it displays the Node JS version, followed by a help message and presents a prompt > awaiting further instructions. Go ahead and type .help, which as shown in listing 6-1 further displays other commands available in the node REPL mode.

At this point, you can enter any JavaScript statement at the node REPL prompt to be evaluated. Listing 6-2 contains a series of JavaScript statements you can try out.

Listing 6-2. JavaScript statements evaluated in node REPL mode
> Math.PI
3.141592653589793
> 2**5
32
> let letter = 'a'
undefined
> let echoer = function(message) { 
   return message;
}
undefined
> echoer(letter)
'a'
> process.versions.v8
'7.4.288.21-node.17' 

The first JavaScript statement Math.PI in listing 6-2 evaluates to 3.141592653589793, what's interesting about this statement is not so much the result, but rather that the Node JS REPL provides access to the JavaScript built-in Math data type. The second JavaScript statement 2**5 ("2 to the power 5") in listing 6-2 evaluates to 32, here again the mathematical result isn't what's interesting, but rather the use of the JavaScript exponentiation operator ** which is a new syntax from ECMAScript2016 (ES7), confirming the Node JS REPL uses a fairly updated JavaScript engine.

The third JavaScript statement let letter = 'a' is a simple JavaScript assignment statement which outputs undefined because evaluating an assignment never returns a result, however, the statement does make the letter reference available for later access. The fourth JavaScript statement let echoer is a function expression that returns whatever value is passed by a caller, it also outputs undefined because evaluating function expression never returns a result. The fifth JavaScript statement in listing 6-2 evaluates calling the echoer function expression with the letter reference, an evaluation that results in 'a' which is the value of the letter reference.

Finally, the last JavaScript statement in listing 6-2 evaluates the process.versions.v8 reference. Although the process.versions.v8 reference is a somewhat advanced Node JS topic, it provides some interesting insight. Recall that back in figure 6-1 I mentioned how a Node JS installation at its core uses the same V8 JavaScript engine built-in to the Google Chrome browser, it turns out the output of the process.versions.v8 reference indicates the V8 engine used by the Node JS installation, which in this case corresponds to V8 7.4.288.21-node.17 and corresponds to the same V8 engine used by Google Chrome Browser version 74, in accordance with the V8 version numbering scheme [6].

Now let's use some of the Node JS REPL commands illustrated in listing 6-1. After you type JavaScript statements like the ones in 6-2 you can save them to a file for posterity with the .save command illustrated in listing 6-3.

Listing 6-3. Save statements introduced in node REPL to file
> .save myscript.js
Session saved to: myscript.js
> <Type .exit or Ctrl-D with keyboard to exit>
<Analyze contents of myscript.js>

The .save myscript.js syntax in listing 6-3 tells the Node JS REPL to save all the evaluated JavaScript statements to a file named myscript.js, where myscript.js is a file in the present working directory where Node JS REPL was started. If you exit the Node JS REPL with the .exit command or Ctrl-D keyboard combo, you'll be able to confirm the generated file contains all the evaluated JavaScript statements in plain JavaScript syntax.

Now let's use the Node JS REPL .load statement illustrated in listing 6-4 to demonstrate how it's possible to renew a Node JS REPL with JavaScript statements provided in a file.

Listing 6-4. Load statements in node REPL from a file
[user@laptop]$ node
Welcome to Node.js v12.2.0.
Type ".help" for more information.
> .load myscript.js
...
...
> echoer("Hello Node JS REPL!")
'Hello Node JS REPL!'

The .load myscript.js syntax in listing 6-4 tells the Node JS REPL to load the JavaScript statements from the file named myscript.js, in this case myscript.js is the file generated in listing 6-3, but it could equally be any file with valid JavaScript statements. Once the JavaScript statements are loaded into the Node JS REPL with .load, it's possible to leverage the declarations as if you'd typed them in yourself. Notice in listing 6-4 the statement echoer("Hello Node JS REPL!") outputs 'Hello Node JS REPL!' which works because the myscript.js has a function expression named echoer.

Node JS node: A JavaScript syntax checker

Although the JavaScript REPL from the last section is a great feature offered by the node executable, this doesn't mean it's the only functionality offered by the node executable. The node executable also supports the -c or --check flag to check JavaScript syntax. To test this node feature, I recommend you purposely modify a JavaScript file to include an invalid JavaScript statement (e.g. modify a let statment to et) and run it using the process shown in listing 6-5.

Listing 6-5. Check JavaScript syntax with node -c--check flag
[user@laptop]$ node -c myscript.js
[user@laptop]$ node -c broken_script.js
/broken_script.js:4
et echoer = function(message) { 
   ^^^^^^

SyntaxError: Unexpected identifier
    at new Script (vm.js:83:7)
    at checkSyntax (internal/main/check_syntax.js:78:3)
    at internal/main/check_syntax.js:42:3

The first statment node -c myscript.js in listing 6-5 outputs nothing because the myscript.js file contains valid JavaScript statements and also because the -c flag (or --check flag) simply checks for JavaScript syntax errors without executing anything. The second statment node -c broken_script.js is run against the broken_script.js file, which you can see in the output contains a SyntaxError: Unexpected identifier in line 4 of the file (i.e. broken_script.js:4 et echoer = function(message) { ^^^^^^). As you can see from the examples presented in listing 6-5, the node executable with the -c or --check flag can be helpful to quickly pinpoint JavaScript syntax errors in files of any size.

  1. https://nodejs.org/api/modules.html    

  2. https://github.com/nodejs/release    

  3. https://nodejs.org/en/download/    

  4. https://www.windows-commandline.com/set-path-command-line/    

  5. https://opensource.com/article/17/6/set-path-linux    

  6. https://v8.dev/docs/version-numbers