Welcome to the Node.js for Administrators Course. This course will teach you many of the essentials for administrating and developing with Node.js. The course can be taken with any recent version of Node.js on any platform (Windows, Max OS X, Linux, SunOS) and any supported processor architecture (32-bit or 64-bit). To complete many of the exercises, the reader will need root privileges on their computer if they are using Mac OS X or Linux. The course begins with a review of conventions used in this document then proceeds to the administration and software development content about Node.js.
To help the reader, this document follows several conventions.
Node.js runs on a variety of platforms. On each platform, the command prompt or terminal is called by different names. For the sake of simplicity, when referring to the command prompt or terminal, the term terminal will be used.
For commands that should be executed from the platform's terminal, a $ is used.
$ <enter some command here and press enter>
For multiple commands, the following convention is used.
$ <enter the first command here and press enter>
$ <enter the second command here and press enter>
Observe how each terminal command begins with a $ . After typing the command, you will press enter to execute the command. The $ represents a generic terminal prompt. The terminal prompt on your computer will most likely be different.
When entering commands into the Node.js interactive shell, the commands will be formatted as follows.
> <enter some Node.js interactive shell command here and press enter>
Observe how each Node.js interactive shell commands being with > . The character > is the default Node.js interactive shell command prompt.
Finally, when programming code should be typed in a text editor (any text editor can be used, but we recommend the cross-platform, JavaScript based Atom editor ), the code will be represented as follows.
console.log("Hello World!");
Observe how there is no $ and no > at the beginning of the line. Programming code will have no prompt. Unless otherwise stated, all programming code will be written in JavaScript.
Traditionally, JavaScript has been limited to the web browser. With the advent of Node.js, JavaScript can run on any platform that supports Google's V8 JavaScript engine. Such platforms include Microsoft Windows, Mac OS X, SunOS and the many flavors of Linux. Google's V8 JavaScript engine was written for its Chrome Web Browser, but Node.js does not run within a web browser. This allows JavaScript to be written and executed on any platform that supports Google's V8 engine even if Chrome does not run on it. One huge advantage to running outside of the web browser is that Node.js is not subject to the same security limitations that constrains JavaScript in the web browser. Node.js applications can access the file system, interact with the networking system of the computer and perform many additional tasks similar to any other programming language such as C++, C# or Java.
Even with the increased capabilities of JavaScript through Node.js, fundamental principles such as single-threaded operation, the JavaScript event loop, etc... all apply in Node.js because Node.js is still running JavaScript and as such the underlying design and architectural principles of JavaScript very much apply.
JavaScript is single-threaded; therefore, it does not support true concurrency. Efficiently written JavaScript appears to be concurrent through the use of an event loop. At it's core, JavaScript is event driven. An event occurs, a task is pushed on to the event queue, the tasks are executed in order and upon completion the next task on the queue is executed.
The JavaScript event loop executes tasks in order using a run-to-completion model. Once JavaScript begins the execution of a task, it does nothing else until the task has been completed, then JavaScript processes the next task. To improve JavaScript performance, developers should write their code such that each task is as quick as possible, so that the JavaScript engine can process the next task as quickly as possible. A good rule of thumb is that each task should execute in under 100ms.
To minimize the amount of time each task takes, all API calls from within Node.js, especially I/O operations, are asynchronous (in many cases synchronous versions of methods are available but should only be used during the application's start up phase before it begins to perform its primary purpose). While the application's JavaScript code is single-threaded, the Node.js internals that handle API calls do so by using multiple threads and other traditional concurrent programming features of the underlying operating system. Nevertheless, the results of these asynchronous operations are handled via callback functions that are pushed on to the JavaScript event loop upon completion of the API call. To sum it up, its commonly said, "Everything in Node.js runs in parallel; except, your code".
While JavaScript is single-threaded, and only one Node.js process can run on a given processor/core, Node.js itself can run one copy of itself on each processor/core (also known as CPUs within Node.js's process API). Using a Node.js module like cluster, multiple Node.js processes running on different CPUs can be coordinated and provide increased throughput and reliability to processing client requests.
Installing Node.js is a relatively simple task. For Windows and Mac OS X users, installer applications are available directly from the Node.js web site . For computers running Windows, Mac OS X, SunOS and Linux pre-compiled binaries are available. For users who desire to build a fresh copy of Node.js, the Node.js source code is available for download from the Node.js web site. Finally, for Linux computers running distros that are either RPM based of Debian based, Node.js can be installed with their respective package managers.
Installing on Windows and Mac OS X is as easy as running the binary installer available on the Node.js web site at http://nodejs.org/ .
To install Node.js on Linux, there are three options: Linux packages, pre-compiled binaries, and local source code compilation. Linux packages are available from nodesource.com . Below are the instructions for installing Node.js packages on Debian based (Ubuntu) and Red Hat based (Fedora, CentOS) Linux distros.
Debian based Linux Distros
$ curl -sL https://deb.nodesource.com/setup | bash -
$ sudo apt-get install -y nodejs
RPM based Linux Distros
$ curl -sL https://rpm.nodesource.com/setup | bash -
$ sudo yum install -y nodejs
The latest versions of Ubuntu (Debian-based) and CentOS (RPM-based) contain Node.js and the Node Package Manager in their package repositories. Unfortunately, these versions are not usually the latest versions of Node.js. Its better to use the **nodesource.com repositories above. If you choose to install Node.js and the NPM package manager from the standard Debian or RPM repositories, the package ids for both Linux Package Management systems are nodejs and npm . When installing with the **nodesource.com repositories, both Node.js and NPM and installed via the nodejs package.
Pre-compiled binaries are available for all four platforms (Windows, OS X, Linux, SunOS) and come in 32-bit and 64-bit architecture varieties. To download a pre-compiled binary, navigate to the URL http://nodejs.org/download/ .
To use the pre-compiled binary for Windows, download the exe file appropriate for the computer's architecture (32-bit or 64-bit) and execute it. A Node.js REPL terminal will appear and JavaScript can be executed. The pre-compiled binary for Windows does not come with the Node Package Manager.
To use the pre-compiled binaries for Mac OS X, SunOS and Linux, download the appropriate gzipped tarball for your computer's platform and architecture and complete the following steps.
To download the pre-compiled binaries for Node.js from the command line execute one of the two following commands (replacing the URL with the URL appropriate for your computer's platform and architecture.
$ wget http://nodejs.org/dist/v0.10.35/node-v0.10.35-linux-x64.tar.gz
or
$ curl -O http://nodejs.org/dist/v0.10.35/node-v0.10.35-linux-x64.tar.gz
Both commands download the gzipped tarball to the current folder; therefore, only execute one of them.
The next step is to unzip and unarchive the gzipped tarball. Be sure to replace the filename listed in the example below with the name of the file you downloaded.
$ gzip -d node-v0.10.35-linux-x64.tar.gz
$ tar -xf node-v0.10.35-linux-x64.tar.gz
The -d option tells gzip to decompress the file. The -x option tells tar to extract the archive. The -f option tell tar the archive is a file (as opposed to a tape drive or something else).
Or, you perform the unzip and unarchive with one command.
$ tar -zxf node-v0.10.35-linux-x64.tar.gz
The -z option tells tar to unzip the file before extracting the archive.
The next step is to copy the Node.js files to the desired location on your computer, and setting up symbolic links so that all users can run it from the command line. There are many ways to deploy the files, the key is to setup the symbolic links correctly. A typical location to copy the node files to is the /usr/local folder. To copy the files, type the following command with root privileges in a terminal window.
$ sudo mv node-v0.10.35-linux-x64 /usr/local
After moving the files, two symbolic links need to be created.
$ ln -s /usr/local/node-v0.10.35-linux-x64/bin/node /usr/local/bin/node
$ ln -s /usr/local/node-v0.10.35-linux-x64/bin/npm /usr/local/bin/npm
After the symbolic links have been created, Node.js is ready to be used.
If you require a customized build of Node.js or your platform architecture is not supported then you can download the Node.js source code and create a customized build of Node.js. The following instructions are for Linux-based systems only. To compile Node.js on Microsoft Windows or Mac OS X requires Microsoft Visual Studio Express or XCode, respectively.
To download the Node.js source code from a terminal, execute one of the following two commands below. Be sure to modify the version number to reflect the version you are intending to download.
$ wget http://nodejs.org/dist/v0.10.35/node-v0.10.35.tar.gz
or
$ curl -O http://nodejs.org/dist/v0.10.35/node-v0.10.35.tar.gz
Both commands download the gzipped tarball to the current folder; therefore, only execute one of them.
The next step is to unzip and unarchive the gzipped tarball. Be sure to replace the version number listed in the example below with the version number of the file you downloaded.
$ gzip -d node-v0.10.35.tar.gz
$ tar -xf node-v0.10.35.tar.gz
The -d option tells gzip to decompress the file. The -x option tells tar to extract the archive. The -f option tell tar the archive is a file (as opposed to a tape drive or something else).
Or, you perform the unzip and unarchive with one command.
$ tar -zxf node-v0.10.35.tar.gz
The -z option tells tar to unzip the file before extracting the archive.
Change to the folder containing the source code and type the following command. DO NOT RUN this command with root privileges.
$ ./configure
If you get an error complaining that no compiler has been installed, then that means Linux development tools need to be installed on the computer.
On Debian or RPM based Linux distros, development tools can be installed through one of the two package manager commands. To install development tools on Debian-based systems, run the following command from a terminal window with root privileges.
$ sudo apt-get install -y build-essential
To install developments tool on RPM based Linux distros run the following command with root privileges from a terminal.
$ sudo yum groupinstall -y 'Development Tools'
Once the development tools are installed, run the configure command again from the terminal window in the root folder of the source code. DO NOT RUN the configure command with root privileges.
The configure command should execute quickly. Once configure successfully executes, run the make command. DO NOT RUN the make command with root privileges.
$ make
The make command will take a few minutes to complete depending upon the hardware specifications of your computer.
Testing the Build Results
If you desire to test the results of the build process before installing it, execute the following command from a terminal window before executing the make install command.
$ make test
The testing in process will take several minutes to complete. Some tests may fail, yet, Node.js will work as expected. Feel free to explore why the tests failed, but most likely all is well.
Once the make command completes, execute the make install command with root privileges from the terminal. Root privileges are needed to copy files to and make symbolic links in privileged system folders. Only run commands as root when absolutely needed.
$ sudo make install
Once the make install command completes, Node.js is installed and can be used.
Once Node.js is installed (regardless of installation method), it is used by running the node command from the a terminal. Node.js can be used in REPL mode or it can be used to execute JavaScript files. To execute Node.js in REPL mode, run the node executable from the command line.
$ node
You will be presented with a Node.js command prompt from which JavaScript commands can be executed. To execute a JavaScript file with Node.js, run the node executable like this:
$ node somefile.js
In this example, somefile.js represents a JavaScript source code file.
To simply view the version number of the installed Node.js executable, execute the following command from the terminal window.
$ node -v
If a version number is displayed, then Node.js has been installed successfully.
Step 1. If your computer's platform is Windows or OS X, download the installer and execute it. Select, the default options for completing the installation. If you computer's platform is Linux, download and install Node.js using the appropriate package manager. Once installation is complete, run the node executable to output the version number.
Step 2. Download the pre-compiled binaries for your platform. Extract the binaries and change to the executables folder. Run the node executable in the folder and output the version number.
Exercise Complete!
Challenge: If your platform is Linux, download the source code, compile it and run the resulting node.js executable outputing the version number. If you cannot compile the source code because the compiler is missing be sure to download and install the development tools packages.
Upgrading Node.js is fairly simple. For installations using the installer application or Linux Package Managers, upgrading is as simply as running the latest installer or updating the installed packages.
Download the latest Node.js version of the installer application for your computer's platform and architecture and execute it. It will upgrade your computer's version of Node.js.
For Node.js installations performed via Linux Package Managers, upgrading Node.js is nothing more than performing a package upgrade.
To upgrade Node.js with Debian Package Manager based Linux distros, run the following command as root (normally via sudo).
$ sudo apt-get upgrade -y nodejs
To upgrade Node.js on RPM based Linux distros, run the following as root (normally via sudo).
$ sudo yum update -y nodejs
After the update is performed, confirmation of the update can be done by executing the following command from a terminal.
$ node -v
The version number displayed will match the version upgraded to, if the upgrade was successful.
To update an existing Node.js installation with latest pre-compiled binaries simply perform the same steps as installing a pre-compiled Node.js installation.
To update the version of Node.js on a computer with a locally compiled version, simply repeat the steps listed for the initial installation of Node.js from locally compiled source code.
After the update is performed, confirmation of the update can be done by executing the following command from a terminal.
$ node -v
The version number displayed will match the version upgraded to, if the upgrade was successful.
From time to time, when installing, uninstalling, and updating Node.js, the terminal in Linux will give an odd error that looks like this.
$ node
-bash: /usr/sbin/node: No such file or directory
If you type /usr/bin/node and press enter Node.js runs fine. The challenge is that /usr/bin is in your path and the shell is not finding Node.js there. To solve the problem, type the following command in the terminal.
$ hash -r
Then, try to run Node.js again by typing node at the command prompt and pressing enter.
What is the Read-Eval-Print-Loop, more commonly referred to as REPL? When Node.js is executed from a terminal with no JavaScript file specified, it runs as an interactive shell. The Node.js interactive shell reads JavaScript commands entered by the user, evaluates the command, then prints the result of the evaluation. After printing the evaluation, the user enters a new JavaScript command that is executed within the context of the previously entered and evaluated commands.
The REPL has many useful purposes including debugging and trying out new JavaScript commands. In the REPL, JavaScript commands can be a declaration, expression or block statement. Also, they can be single line or multi-line.
Example:
Declarations
> var x = 2;
undefined
> function f() {
... return "some value";
... }
undefined
Example: Expressions
> 4 + 6
10
> x * 5
10
Example: Block Statement
> if (x > 4) {
... console.log("greater than 4");
... } else {
... console.log("less than 4");
... }
less than 4
undefined
Step 1. To start the interactive shell, execute the following command from the terminal.
$ node
Step 2. You will be presented with a Node.js command prompt that looks like this:
>
Step 3. From Node.js command prompt, JavaScript and special Node.js commands can be entered. For example, type the following command:
> console.log("Hello Node.js!");
The output will look similar to this:
> console.log("Hello Node.js!");
Hello Node.js!
undefined
>
The text "Hello Node.js!" is the output of the console.log command. The text "undefined" refers to the return value of console.log . Since console.log does not return a value, the output to the screen is undefined . Every JavaScript command evaluated by Node.js will output the return value of the command, even if there is no return value. This is a JavaScript feature more than a Node.js oddity. In JavaScript, all expressions return a value even if the value is simply undefined .
In addition to a single line expression, multi-line expressions can be entered.
Exercise Complete!
In addition to JavaScript expression and declarations, there are several Node.js control commands that can be entered within the interactive shell. Here is a list of the commands.
Displays a list of all shell commands and their descriptions.
Example: From a Node.js command prompt, type .help then press enter .
> .help
.break Sometimes you get stuck, this gets you out
.clear Alias for .break
.exit Exit the repl
.help Show repl options
.load Load JS from a file into the REPL session
.save Save all evaluated commands in this REPL session to a file
>
Exits the interactive shell. In addition to .exit , ctrl+d can be used to exit the interactive shell. Finally, typing ctrl+c twice exits the interactive shell as well.
Example: From a Node.js command prompt, type .exit , then press enter .
> .exit
$
When typing multi-line commands the .break command is used to exit the multi-line command if you do not want to complete it.
Example: Type the following code at a Node.js command prompt, then press enter .
> function f() {
Observe when you typed the open curly brace and pressed enter, the cursor went to the next line resulting in a multi-line Node.js command.
> function f() {
...
Add some more code like this, and press enter .
> function f() {
... var g = 10;
The result is another line in the multi-line command.
> function f() {
... var g = 10;
...
Type .break and press enter .
> function f() {
... var g = 10;
... .break
Observe, how you exited the multi-line statement and returned to a normal Node.js command prompt.
> function f() {
... var g = 10;
... .break
>
At the Node.js command prompt, type f and press enter .
> f
Observe how the result says f is undefined.
ReferenceError: f is not defined
at repl:1:2
at REPLServer.self.eval (repl.js:110:21)
at Interface.<anonymous> (repl.js:239:12)
at Interface.emit (events.js:95:17)
at Interface._onLine (readline.js:203:10)
at Interface._line (readline.js:532:8)
at Interface._ttyWrite (readline.js:761:14)
at ReadStream.onkeypress (readline.js:100:10)
at ReadStream.emit (events.js:98:17)
at emitKey (readline.js:1096:12)
Because the .break control command was used to exit the multi-line command, the function object was not defined.
Saves the current REPL session to a file.
Example: From a Node.js command prompt, type the following commands, pressing enter after each command.
> var x = 2;
undefined
> var y = 3;
undefined
> x*y
6
Observe, how after each command, the expression value of the command is displayed on the screen. Next, type .save demo.js and press enter , to save the REPL session commands to a file named demo.js .
> var x = 2;
undefined
> var y = 3;
undefined
> x*y
6
> .save demo.js
Exit the Node.js command prompt, and view the contents of demo.js .
> .exit
$ more demo.js
The output will look like this.
$ more demo.js
var x = 2;
var y = 3;
x*y
$
The JavaScript file is a listing of the commands typed during the Node.js REPL session.
Loads a saved REPL session (or any JavaScript code) from a file.
Example: Using the demo.js file from the .save example, type the following from a Node.js command prompt and press enter .
> .load demo.js
Observe the result of loading the file.
> .load demo.js
> var x = 2;
undefined
> var y = 3;
undefined
> x*y
6
>
Each line of the file is executed, displaying the value of each expression.
From the Node.js command prompt, type the following command, and press enter .
> x+y
Observe the outputed value of 5.
> x+y
5
>
When a JavaScript file is loaded, its variable and function declaration are loaded into the context of the REPL environment to be used by future commands.
Clears the context when the REPL is started by executing the start function provided by the repl module.
Example: Create a file named repldemo.js , and add the following JavaScript code to it.
var repl = require('repl');
repl.start({ prompt: "MyREPL> " }).context.message = 'Some message!';
When executed, this JavaScript file create a custom REPL environment by configuring a custom prompt and initializing a variable named message with a value of 'Some message!'. To execute this JavaScript file, type the following command into a terminal and press enter .
$ node repldemo.js
A Node.js command prompt will appears that looks like this.
MyREPL>
At the custom Node.js command prompt type the following command and press enter .
MyREPL> message
The output will look like this.
MyREPL> message
'Some message!'
MyREPL>
Next, type .clear , and press enter .
MyREPL> .clear
The result of executing the .clear Node.js control command is.
MyREPL> .clear
Clearing context...
MyREPL>
Finally, type message , and press enter .
MyREPL>message
ReferenceError: message is not defined
at repl:1:2
at REPLServer.self.eval (repl.js:112:21)
at Interface.<anonymous> (repl.js:239:12)
at Interface.emit (events.js:95:17)
at Interface._onLine (readline.js:203:10)
at Interface._line (readline.js:532:8)
at Interface._ttyWrite (readline.js:761:14)
at ReadStream.onkeypress (readline.js:100:10)
at ReadStream.emit (events.js:98:17)
at emitKey (readline.js:1096:12)
MyREPL>
Because the context was cleared with the .clear command, the variable message is no longer defined. The .clear control command only works in this way within custom REPLs. When used in Node.js's standard REPL, .clear is an alias of .break .
Step 1. From a terminal, start the Node.js interactive shell.
Step 2. Type in the following function.
function formatName(firstName, lastName) {
return String(firstName) + " " + String(lastName);
}
Step 3. Type the following command.
> formatName("John", "Doe");
Step 4. Save the session to a file named sample.js using a control command.
Step 5. Exit the Node.js interactive shell using a control command.
Step 6. Start the Node.js interactive shell again.
Step 7. Load the sample.js file. The loaded JavaScript will execute successfully.
Exercise Complete!
The Node Package Manager is a package manager for Node.js. It's packages are not limited Node.js, any kind of JavaScript module can be distributed as a Node.js package. Node.js packages can be created, installed, updated and uninstalled via the npm command line tool.
The npm performs many operations to help manage Node Packages locally and globally. To see a full list of commands that can executed with npm , type npm in a terminal, then press enter . The following sections will cover many of the commands commonly used by administrators and developers when working with Node.js.
When using NPM errors can occurs. When errors occur, the errors are displayed on the screen and logged to to a file named npm-debug.log .
Node.js projects can be configured with a package.json file to store metadata about a Node.js project including its package dependencies. To setup a package.json file, open a command prompt, change to the project folder, then run the following command.
$ npm init
A number of questions will be asked. The default values can be accepted or specific values can be entered. The result is a JSON file named package.json that will look similar to this.
{
"name": "MyProject",
"version": "1.0.0",
"description": "Description for MyProject",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Some Author",
"license": "Apache2"
}
Once this file is created, package dependencies can be saved to the package.json file. The package.json file can be viewed from two perspectives - it is a project configuration file but it can also serve as the package information file for distributing a project as an NPM package. For ordinary development, this file will be viewed as a project configuration file; but, the project could be distributed as its own package as well.
Step 1. Open a terminal, and change to the folder on your computer where you create new projects. Create a new folder named myproject . Change to the new folder.
Step 2. Type npm init , and press enter . Accept the default options, and complete the file setup.
Step 3. Create the following folders, myproject/app , myproject/dist . Note: myproject refers to the folder created in Step 1 and is merely specified to show the desired folder structure. The app folder will contain the source code files you will edit. The dist folder will contain the code files that will actually run on the web server. We will add a mechanism to automatically process and copy the files from the folder app folder to the dist folder in a future exercise.
Exercise Complete!
Node.js packages can be installed locally in a project or globally on a system. Local packages allow project specific versions of packages to be installed. On OSX and Linux Systems, installing a package globally requires root level access.
To install a package locally within a project, change to the project folder, then run the following command.
$ npm install <package name>
In addition to installing single packages, multiple packages may be installed simultaneously.
$ npm install <package 1 name> <package 2 name> <package 3 name>
Node.js project package dependencies can be saved to the package.json file using one of three options available when installing Node.js packages: save , save-dev , and save-optional .
The save option is for packages that are needed for the project to execute such as a web server package. The save-dev option is for packages that are needed for development such as a CSS minimizer. The save-optional option is for packages that are not required for execution of the project.
To save an installed to package.json file, add the save option.
$ npm install <package name> --save
If the package is used for development purposes only, then use the save-dev option.
$ npm install <package name> --save-dev
To save an optional package to the package.json file, type the following command.
$ npm install <package name> --save-optional
To install a package globally run the following command.
$ npm install -g <package name>
Observe the g option used after the install command. The g option signifies the installation is supposed to be global.
When a package is installed locally, its downloaded to the node_modules folder of the current project. When a package is installed globally, its downloaded to the node installation folder which is generally /usr/local for a default Node.js installation on Linux and Mac. For Windows, the global folder is within the user's folder: C:\Users\SomeUser\AppData\Roaming\npm .
A package should only be installed globally if you intend to invoke it from the command line. Otherwise, the package should be installed locally and referenced with the require method within your JavaScript code. Some packages such as Grunt , are distributed with two packages, one package should be installed locally and a second command line support package that should be installed globally. In those cases, the following commands would be executed from the project folder.
$ npm install grunt
$ npm install -g grunt-cli
Observe that the first package is installed locally, while the second package is installed globally and provides command line access to Grunt.
Step 1. Install the following packages as normal project dependencies. Depending upon your system's configuration, you may need to install these as root using sudo .
Step 2. Install the following packages as project development dependencies.
Step 3. Install the following packages globally.
Step 4. Open the package.json file in a text editor, and add the following section of code. The first few lines and last line of the original file are included to show you where to add the browserify and browserify-shim configuration.
"grunt-contrib-watch": "^0.6.1"
},
"browserify": {
"transform": [
"browserify-shim"
]
},
"browserify-shim": {
"angular": "global:angular"
}
}
These settings are needed to make Angular.js compatible with the CommonJS module system. Save the file, and close it.
Exercise Complete!
Many NPM packages are regularly updated; therefore, the global and local packages installed on your system will need to be updated from time to time. Fortunately, updating NPM packages is a simple process.
To update a single local package, change to the project folder, then run the following command.
$ npm update <package name>
In addition to updating single packages, multiple packages may be updated simultaneously.
$ npm update <package 1 name> <package 2 name> <package 3 name>
To update all of the local packages specified in package.json file, then run the following command from the project folder.
$ npm update
To see a list of outdated packages specified in the package.json file without updating them, change to the project folder, then run the following command.
$ npm outdated
To update a specific global package, run the following command.
$ npm update -g <package name>
Once again, observe the g option signifying this is an update of a global package.
Uninstalling packages causes them to be removed from a project or from the system globally. Additionally, options can be specified to remove from the package.json file.
To uninstall a local package, open a command prompt, change to the project folder, then run the following command.
$ npm uninstall <package name>
In addition to uninstalling single packages, multiple packages may be uninstalled simultaneously.
$ npm uninstall <package 1 name> <package 2 name> <package 3 name>
The uninstall command has an alias named rm . Therefore, package can be removed as shown here.
$ npm rm <package name>
To uninstall a local package and remove it from the package.json file, open a command prompt, change to the project folder, then run the following command.
$ npm uninstall <package name> --save
To remove the package as a development dependency, use the following save-dev option:
$ npm uninstall <package name> --save-dev
To remove the package as an optional dependency, use the following save-optional option:
$ npm uninstall <package name> --save-optional
To remove a package globally, open a command prompt, then type the following command.
$ npm uninstall -g <package name>
In addition to npm uninstall , the command npm rm can be used with the same options to remove packages as well.
Linking a package allows you to make a local package be referenced global. Additionally, other Node.js packages can link to the module to make it a local reference. This can be useful for developing and debugging multiple packages. Additionally, packages can referenced without distributing them from a repository.
To link a package, change to the package folder and run the following command with root user privileges.
$ cd <node package folder>
$ sudo npm link
The result of the command will look similar to this output.
/usr/local/lib/node_modules/<package name> -> /home/<user>/nodejs/<package name>
To link the package to another package, change to the folder of the other package and run the following command.
$ cd <node package folder>
$ sudo npm link <package name>
The output of the command will look similar to this.
/home/<user>/nodejs/<other package name>/node_modules/<package name> -> /usr/local/lib/node_modules/<package name> -> /home/<user>/nodejs/<package name>
Using the require function, the module defined in the package can be included in the other package.
Unlinking package reverses the process of linking packages. To unlink a package from another package, change to the package folder and type the following command.
$ cd <node package folder>
$ npm unlink <package name>
The output of the command would be.
unbuild <node package name>@<node package version>
To unlink a node package from the global node modules folder, change to the package folder and type the following command with root privileges.
$ cd <node package folder>
$ npm unlink <package name>
The output of the command should be.
unbuild <node package name>@<node package version>
If you receive an error, type the following command with root privileges.
sudo npm rm -g <package name>
This will remove the linked package from the global node modules folder.
Step 1. Open a terminal, and create two folders.
$ mkdir firstmod
$ mkdir secondmod
Step 2. Change to the firstmod folder and initialize the package. Accept the defaults for the package.json creation.
$ cd firstmod
$ npm init
Step 3: Create a file named index.js , then add the following code to it.
module.exports = {
someMethod: function() {
console.log("some method from first mod!!!!!!");
}
};
Save the file, and close it.
Step 5. In the terminal, use npm to link the module.
npm link
Note: Depending upon your platform and Node.js configuration, NPM link and unlink commands may require root privileges in order to be executed.
Step 6. In the terminal, change to the secondmod folder. Run npm init , accepting the defaults values for the questions asked.
Step 7. Link the firstmod package to the secondmod package.
npm link firstmod
Step 8. Create an index.js file, then add the following code to it.
(function() {
require("firstmod").someMethod();
}());
Step 9. From the terminal, run the index.js file in secondmod .
node index.js
The output will be.
some method from first mod!!!!!!
Step 10. To unlink firstmod , run the following command from the terminal.
npm unlink firstmod.
Step 11. From the terminal, run index.js with Node.js again. What is the output and why?
Step 12. To complete the unlinking process, change to the firstmod folder and unlink it with the npm -rm command
Exercise Complete!
Packages installed for a package can be listed using npm ls . The ls command will list all of the packages and their dependencies that installed for package.
$ npm ls
The output will look similar to this.
├─┬<EMAIL_ADDRESS>extraneous
│ └──<EMAIL_ADDRESS>├─┬<EMAIL_ADDRESS>extraneous
│ ├──<EMAIL_ADDRESS>│ ├──<EMAIL_ADDRESS>│ ├─┬<EMAIL_ADDRESS>│ │ ├──<EMAIL_ADDRESS>│ │ ├─┬<EMAIL_ADDRESS>│ │ │ ├──<EMAIL_ADDRESS>│ │ │ └──<EMAIL_ADDRESS>│ │ └──<EMAIL_ADDRESS>│ ├──<EMAIL_ADDRESS>Note: The listing can be very long.
The NPM command ls is an alias for npm list . Both can be used interchangeably. Additionally, its possible to list a single package in a package as shown here.
$ npm ls grunt
<EMAIL_ADDRESS>/home/demos/tempproject
└──<EMAIL_ADDRESS>Node.js packages can be configured to be executed with the npm command. To configure a Node.js package to support execution via npm the scripts section must be added to the package.json file.
"scripts": {
"start": "grunt",
"webserver": "node webserver.js"
}
To execute the start script, the following command would be executed from a terminal.
$ npm start
To execute the webserver script with NPM, the following command would be executed from a terminal.
$ npm run webserver
For custom commands like webserver , the NPM command run must be invoked followed by the name of the script. For built-in scripts such as start , the run command is not needed.
Node.js modules Node.js modules follow the CommonJS module specification.
Creating a custom module is very simple. Open a text editor, and add the following code.
module.exports = function () {
"use strict";
return {
doSomething: function() {
console.log("did something");
}
};
};
Basically, the CommonJS module pattern requires creating a function that returns the module object. The function is them assigned to the module.exports property.
To use a module in Node.js, the require command is used. The require command allows you to include a module provided by an NPM package or a JavaScript file name.
To require a module that is an NPM package, the require is used as follows.
var someModule = require("some-module");
To require a module using a JavaScript filename, require can be called as follows.
var someModule = require("./js/some-module");
Notice, the .js is not explicitly stated in the filename. The .js is assumed and will be applied when the file is loaded up by the require function.
Once a module is loaded up, the JavaScript object returned from require is used like any other JavaScript object.
someModule.doSomething();
Step 1. From a terminal, change to the app folder.
Step 2. Create a new file named index.html , add the following code to it.
<!DOCTYPE html>
<html>
<head>
<title>Angular.js Project Scaffolding</title>
<link href="css/bootstrap.min.css" type="text/css" rel="stylesheet">
<link href="css/bootstrap-theme.min.css" type="text/css" rel="stylesheet">
<link href="css/app.min.css" type="text/css" rel="stylesheet">
</head>
<body>
<div ng-app="MyApp">
<div ng-controller="MyCtrl">
<h1>{{message}}</h1>
</div>
</div>
<script src="js/angular.min.js"></script>
<script src="js/app.js"></script>
</body>
</html>
Save the file, and close it.
Step 3. From the terminal, create a new folder named js in the app folder. Change to the js folder.
Step 4. Create a new file named app.js , and add the following code to it.
module.exports = (function(global, $, angular) {
"use strict";
require("./app.constants.js");
return angular.module("MyApp", ["MyApp.Constants"])
.controller("MyCtrl", ["$scope", "Greeting", function($scope, Greeting) {
$scope.message = Greeting;
}]);
}(window || global, require('jquery'), require("angular")));
Save the file, and close it. This file will be the main module of the application.
Step 5. Create a new file named app.constants.js , and add the following code to it.
module.exports = (function(global, $, angular) {
"use strict";
return angular.module("MyApp.Constants", [])
.constant("Greeting", "Hello World!!!!");
}(window || global, require('jquery'), require("angular")));
Save the file, and close it. This file will be the constants module of the application.
Step 6. From the terminal, change to the app folder. Create a new folder named less in the app folder. Change to the less folder.
Step 7. Create a new file named app.less , add the following code to the file.
h1 { color:blue; }
Save the file, and close it.
Exercise Complete!
Node.js provides several modules for configuring and running a web server. The three modules are the http module, the connect module, and the express module. The following sections will examine each module, demonstrating how to setup a web server. The lowest level module is the http module. It is built into Node.js and does not need to be installed locally into each project.
This module provides the simplest web server with very few options. Requests from web clients can be processed and responses sent in reply.
The Connect module builds upon the http module to provide additional capabilities.
The connect module is not bundled with Node.js and must be installed using NPM. To install the module type the following command.
$ npm install connect --save
$ npm install serve-static --save
The save option, adds the Connect and Server Static module dependencies to the package.json file. For more information on packages, see the NPM Packages section.
The following example is going to demonstrate how to setup a simple Connect web server that serves static content. The Connect server comes with several supporting modules. In this example, the serve-static module is being referenced to load up static content.
var
http = require("http"),
connect = require('connect'),
serveStatic = require('serve-static');
Observe the three require functions, loading the http , connect and serve-static modules. Only module names are needed because the modules have been loaded via NPM into the node_modules folder for the project.
The next snippet of JavaScript demonstrates how to create a Connect web server object and configure a file path to serve static content from.
var app = connect();
app.use(serveStatic("./www"));
Finally, using the http module a web server is fired up on port 8080 and will serve content from the folder specified in the previous snippet.
var webServer = http.createServer(app);
webServer.listen(8080);
The express module is not bundled with Node.js and must be installed using NPM. To install the module type the following command.
$ npm install express --save
$ npm install body-parser --save
The save option, adds the connect module dependency to the package.json file. For more information on packages, see the NPM Packages section.
The following example is going to demonstrate how to setup a simple Express web server that serves static content and can process HTTP request bodies. The Express server comes with several supporting modules. In this example, the body-parser module is being referenced to process the body content of HTTP requests.
var
http = require("http"),
express = require('express'),
bodyParser = require('body-parser');
Observe the three require functions, loading the http , express and body-parser modules. Only the module names are needed because the modules have been downloaded via NPM into the node_modules folder for the project.
To create the Express server, the express module is called as a function.
var app = express();
Using the use function, the Express server can be configured to process many kinds of web server requests and serve up many kinds of content responses. The code below will serve static web content such as HTML files from the www folder. Also, HTTP requests that have a content body will be able to be parsed by the body-parser module. Express supports many kinds of modules to processing requests, one example is a cookie parsing module.
app
.use('/', express["static"]("./www"))
.use(bodyParser.json());
Finally, in similar fashion as the Connect server, the Express server will use the http module to fire up a web server on port 8080 using the configuration specified in the previous snippet.
var webServer = http.createServer(app);
webServer.listen(8080);
Setting up Express to support SSL is relatively simple. Instead of using the http module, the https module is used. The https module functions very similarly to the http module and supports the same events for creating a server as the http module supports.
Here is some sample code demonstrating how to setup an SSL connection using the https module.
var https = require('https');
var fs = require('fs');
var options = {
key: fs.readFileSync('keys/key.pem'),
cert: fs.readFileSync('keys/cert.pem')
};
https.createServer(options, function (req, res) {
res.status(200).send("hello world\n");
}).listen(8000);
The fs module is required to read the private key and the public certificate. The private key and public certificate are then passed as options in the https module to initialize and start the SSL-enabled web server.
An alternative option to configuring SSL directly on Express is to use a reverse proxy server like Nginx to handle SSL connections allowing the Node.js application to focus on serving content.
Step 1. From a terminal, change to the myproject folder.
Step 2. Create a new file named webServer.js , add the following code to it. Copy and paste the code from this document being sure to actually review the code to understand what it is doing.
module.exports = function (webServerOptions, dbSqlLiteOptions) {
"use strict";
return {
start: function () {
var
http = require("http"),
express = require('express'),
bodyParser = require('body-parser'),
q = require("q"),
restService = require("./restService.js"),
webSockets = require("./webSockets.js"),
app = express(),
appStart = q.defer(),
webServer, restServiceCloseDb, webSocketsCloseDb;
setTimeout(function () {
// initialize the express web server and set a static route
app
.use('/', express["static"](webServerOptions.rootFolder))
.use(bodyParser.json());
// if database options are set then add db config and routes
if (dbSqlLiteOptions) {
restServiceCloseDb = restService(app, dbSqlLiteOptions).configureRoutes();
}
// start listening...
webServer = http.createServer(app);
webServer.listen(webServerOptions.port, function () {
// setup WebSocketServer
webSocketsCloseDb = webSockets(webServer, dbSqlLiteOptions);
var cleanUpExecuted = false;
function cleanUp(fn) {
var p;
if (!cleanUpExecuted) {
p = (fn instanceof Array) ? q.all(fn) : fn();
p.then(function() {
console.log("exiting...");
process.exit();
});
cleanUpExecuted = true;
}
}
//do something when app is closing
process.on('exit', cleanUp.bind(null, [webSocketsCloseDb, restServiceCloseDb]));
//catches ctrl+c event
process.on('SIGINT', cleanUp.bind(null, [webSocketsCloseDb, restServiceCloseDb]));
//catches uncaught exceptions
process.on('uncaughtException', cleanUp.bind(null, [webSocketsCloseDb, restServiceCloseDb]));
appStart.resolve();
});
}, 0);
return appStart.promise;
}
};
};
Save the file, and close it.
Step 3. Create a new file named restService.js , add the following code to it. Copy and paste the code from this document being sure to actually review the code to understand what it is doing.
module.exports = function(app, options) {
var
myApp = app,
myOptions = options,
fs = require("fs"),
sqlite3 = require("sqlite3").verbose(),
q = require("q"), db,
dbExists = fs.existsSync(myOptions.file);
// create and initialize the database if it does not exist
if(!dbExists) {
console.log("Creating database file: " + myOptions.file);
fs.openSync(myOptions.file, "w");
db = new sqlite3.Database(myOptions.file);
db.serialize(function() {
console.log("Creating tables.");
db.run("create table widgets (id integer primary key, name text not null, description text, color text, size text, quantity int not null)");
db.run("create table eventlog (id integer primary key, source text not null, message text not null, severity int not null, created datetime not null)");
console.log("Creating sample data.");
db.run("insert into widgets (name, description, color, size, quantity) values ('Red small gear', 'A red gear that is small.', 'red', 'small', 100)");
db.run("insert into widgets (name, description, color, size, quantity) values ('Green large gear', 'A green gear that is large.', 'green', 'large', 10)");
db.run("insert into widgets (name, description, color, size, quantity) values ('Blue tiny gear', 'A blue gear that is tiny.', 'blue', 'tiny', 45)");
db.run("insert into widgets (name, description, color, size, quantity) values ('Orange medium gear', 'An orange gear that is medium.', 'orange', 'medium', 23)");
});
} else {
db = new sqlite3.Database(myOptions.file);
}
return {
configureRoutes: function() {
// updates an existing record
myApp.put('/svc/widgets/:widgetId', function(req, res) {
var widget = req.body;
db.serialize(function() {
stmt = db.prepare("update widgets set name = ?, description = ?, color = ?, size = ?, quantity = ? where id = ?");
stmt.run(widget.name, widget.description, widget.quantity, widget.color, widget.size, req.params.widgetId, function(err) {
if (err) console.log(err);
res.json({ widgets_updated: this.changes });
});
stmt.finalize();
});
});
// inserts a new record
myApp.post('/svc/widgets', function(req, res) {
var widget = req.body;
db.serialize(function() {
stmt = db.prepare("insert into widgets (name, description, color, size, quantity) values (?, ?, ?, ?, ?)");
stmt.run(widget.name, widget.description, widget.color, widget.size, widget.quantity, function(err) {
if (err) console.log(err);
res.json({ widget_id: this.lastID});
});
stmt.finalize();
});
});
// deletes an existing record with the specified post id
myApp["delete"]('/svc/widgets/:widgetId', function(req, res) {
db.serialize(function() {
stmt = db.prepare("delete from widgets where id = ?");
stmt.run(req.params.widgetId, function(err) {
if (err) console.log(err);
res.json({ widgets_deleted: this.changes });
});
stmt.finalize();
});
});
// gets all records
myApp.get('/svc/widgets', function(req, res) {
db.serialize(function() {
db.all("select * from widgets", function(err, widgets) {
if (err) console.log(err);
res.json(widgets);
});
});
});
// gets a record by id
myApp.get('/svc/widgets/:widgetId', function(req, res) {
db.serialize(function() {
db.get("select * from widgets where id = ?", [req.params.widgetId], function(err, widget) {
if (err) console.log(err);
res.json(widget);
});
});
});
// returns a function to close the database
return function() {
var deferred = q.defer();
console.log("closing the database");
db.close(function() {
console.log("database closed");
deferred.resolve();
});
return deferred.promise;
};
}
};
};
Save the file, and close it.
Step 4. Create a new file named webSockets.js , add the following code to it. Copy and paste the code from this document being sure to actually review the code to understand what it is doing.
module.exports = function(webServer, options) {
"use strict";
var
WebSocketServer = require('ws').Server,
wss = new WebSocketServer({ server: webServer }),
sqlite3 = require("sqlite3").verbose(),
db = new sqlite3.Database(options.file);
wss.on("connection", function(ws) {
console.log("web sockets open");
ws.on("error", function(data) {
console.log("web sockets error");
});
ws.on("close", function(data) {
console.log("web sockets closed");
});
ws.on("message", function(data) {
db.serialize(function() {
var
message = JSON.parse(data),
stmt;
if (message.messageType === "log") {
stmt = db.prepare("insert into eventlog (source, message, severity, created) values (?, ?, ?, ?)");
stmt.run(message.messageData.source, message.messageData.message, message.messageData.severity, new Date(), function(err) {
if (err) {
console.log(err);
ws.send(err);
} else {
ws.send("log request processed");
}
});
stmt.finalize();
}
});
});
// returns a function to close the database
return function() {
var deferred = q.defer();
console.log("closing the database");
db.close(function() {
console.log("database closed");
deferred.resolve();
});
return deferred.promise;
};
});
};
Save the file, and close it.
Exercise Complete!
Helmet is an Express middleware module that is used to help enhance Express security. Helmet provides protection using Content Security Policy, XSS Filter, Click-Jacking, HTTP Strict Transport Security, and many other features. Essentially, Helmet produces response headers that the browser can choose to use to enforce certain client-side security options. Helmet cannot enforce the client-side security options and for older browsers they may not even support them. Nevertheless, Helmet is very helpful to make your application as secure as it can be on the client-side.
To get started with Helmet, install the Node.js package within the Node.js application.
$ npm install helmet --save
After installing Helmet, the Helmet module must be required as such.
var helmet = require('helmet');
To use the default security settings that Helmet offers, use the following code.
var app = Express();
app.use(helmet());
In many cases, you will want to customize Helmet's configuration. The following sections cover the most common configuration options in more detail.
Content Security Policy is geared towards protecting against cross-site scripting attacks. It accomplishes this mission by informing the browser of safe sources of content through setting the Content-Security-Policy response header. CSP can control the sources for most any kind of content that the browser downloads to display a web page such as JavaScript, images, stylesheets, fonts, etc...
Below is some sample code demonstrating how to configure CSP using Helmet.
app.use(helmet.csp({
defaultSrc: ["'self'"],
scriptSrc: ["'cdnjs.cloudflare.com'"],
styleSrc: ["'cdnjs.cloudflare.com'"],
fontSrc: ["'cdnjs.cloudflare.com'"]
}))
In the example above, Helmet is being configured to allow script, style and font downloads from a popular CDN service. In addition, to the options listed above there are many more options that are available for configuration. They include imgSrc , connectSrc , objectSrc , mediaSrc , frameSrc , sandbox , eportUri , reportOnly , setAllHeaders , and safari5 .
If none of the other source values are set, then the default source value will be used. The self value for default means to allow content from the same origin.
The XSS filter helps to protect vulnerable versions of Internet Explorer against an XSS exploit by sending a header to disable XSS protection.
app.use(helmet.xssFilter());
The header for versions of IE with the exploit looks like this.
X-XSS-Protection: 0
For browsers without the exploit, the header looks like this.
X-XSS-Protection: 1; mode=block
Click-jacking it attempting to deceive the user into clicking something on a web page other than what they think they are clicking on. Loading familiar web pages into an iFrame with no border then surrounding that content with malicious links can fool a user into clicking something they do not really intend to click. Using the X-Frame response header, Helmet will indicate to the web browser if the web page can be loaded into an iFrame.
To not allow the web page to be loaded into an iFrame, configure Helmet like this.
app.use(helmet.xframe());
The result X-Frame-Options response header sent to the browser looks like this.
X-Frame-Options: DENY
To allow the web page to be loaded into an iFrame within a web page from the same origin, use the following Helment configuration.
app.use(helmet.xframe('sameorigin'));
The result X-Frame-Options response header sent to the browser looks like this.
X-Frame-Options: SAMEORIGIN
To allow the web page to be loaded into an iFrame for a specific URL, use the following Helmet configuration.
app.use(helmet.xframe('allow-from', 'http://www.somedomain.com'));
The result X-Frame-Options response header sent to the browser looks like this.
X-Frame-Options: ALLOW-FROM http://www.somedomain.com
HTTP Strict Transport Security (HSTS) is a method to inform user agents to use HTTPS instead of HTTP. To configure Helmet to use HSTS, review the following code.
app.use(helmet.hsts({
maxAge:<PHONE_NUMBER>, // 30 days in milliseconds
includeSubdomains: true
}));
The above configuration will inform the user agent to make HTTPS request only for the next 30 days and to include all subdomains.
The HSTS response header to the browser will as follows.
Strict-Transport-Security: max-age=2592000; includeSubDomains
Kraken is useful for larger Express applications. Express does little to help isolate controller logic, from views and models and other content. Kraken lays on top of Express to help structure these components to better facilitate larger application development.
From a system administration perspective, the most interesting aspect of Kraken is the security middleware module named Lusca. Lusca can be be used independent of Kraken and functions similar to Helmet.
To install Lusca, use NPM to install the lusca package.
$ npm install lusca --save
Once installed, the Lusca module needs to be required as demonstrated here.
var lusca = require('lusca');
Lusca has many of the same configuration options as Helmet. Here is a sample Lusca configuration.
app.use(lusca({
csrf: true,
csp: { policy: {
'default-src': "'self'",
'script-src': "'cdnjs.cloudflare.com'",
'style-src': "'cdnjs.cloudflare.com'",
'font-src': "'cdnjs.cloudflare.com'"
}},
xframe: 'SAMEORIGIN',
p3p: 'ABCDEF',
hsts: {maxAge: 2592000, includeSubDomains: true},
xssProtection: true
}));
There is one additional options offered by Lusca that is not covered by Helmet. The P3P option stands for the Platform for Privacy Preferences Project. This option communicates to end users what kind of data will be collected from them by the web site.
An instance of Node.js is limited to one process with one thread. This is not so much a Node.js limitation as it is a JavaScript language limitation. JavaScript both on the client and server is single-threaded. As mentioned at the beginning of the document, what gives JavaScript and more specifically Node.js in this case, the appearance of concurrency is its fast running event loop that depends upon non-blocking execution achieved through asynchronous programming patterns. Nevertheless, Node.js can scale through the creation of multiple instances where one instance runs per processor/core. The management and configuration of the instances can be achieve through several approaches. When standing up a Node.js web server, the two most commonly used approaches is to utilize the cluster module or use a reverse proxy server to map incoming client connections to multiple Node.js instances.
Because Node.js is single-threaded, an Express web server cannot serve requests from multiple threads. To fully utilize computers with multiple processors and multiple cores per processor, multiple Node.js processes (one for each processor/core) can be coordinated from a master Node.js process to serve more requests. From a stability perspective, if a single web server process crashes for any reason, no more requests will be able to be handled until its restarted. There is no fault-tolerant, automatic fail over capability available within Node.js when running a single Node.js process instance, of a single-threaded web server.
To solve this problem, there is a cluster module that will enable Node.js to run multiple processes, each with their own Express web server. To utilize the Cluster module, the Cluster NPM package needs to be locally installed, using the following command.
$ npm install cluster --save
After the Cluster module is installed, it can be used to launch a Node.js process for each CPU available on the computer. According to Node.js, the number of CPUs is the number of physical processors multipled by the number of cores per processor.
(function() {
"use strict";
const
express = require("express"),
cluster = require("cluster"),
app = express();
if (cluster.isMaster) {
var cpuCount = require('os').cpus().length;
while (cpuCount--) {
cluster.fork();
}
} else {
app.get("/", function(req, res) {
res.send('Hi from worker: ' + cluster.worker.id);
});
app.listen(8888);
console.log("Express App is running with worker id " + cluster.worker.id + "...");
}
}());
A single script is used to setup the Master as well as spawn the Child processes.
Nginx is a very popular web server that quickly serves static content while using a reverse proxy approach to serving up dynamic content produced by languages such as PHP, .NET, Java and Node.js. Static content include plain HTML files, image files, JavaScript files, CSS styles and many other kinds of media files. Nginx efficiently handles requests for static content and even provides caching capabilities. A reverse proxy is a proxy that stands in front of several non-public servers providing the client a single point of entry and then maps the various client requests to the appropriate non-public server behind the proxy.
The first question is why use Nginx (or any web server as reverse proxy) instead of simply standing up Express on its own? There are many debatable reasons for doing this setup. Reasons include:
The second question is why choose Nginx over other options?
Usually Express and Node.js are configured web applications through a proxy web server such as Nginx. In this section, we are going to learn how to install and configure Nginx to serve Node.js Express web applications.
To install Nginx on Debian-based Linux distros, type the following command at a terminal.
$ apt-get install nginx
To install Nginx on RPM-based Linux distros, type the following command at a terminal.
$ yum install nginx
As part of the package installation for both Debian-based and RPM-based distros, the Nginx web server should start automatically on port 80. To test, run the following command from a terminal.
$ curl -i localhost
If installed successfully, the output will be a Welcome to nginx! web page.
The nginx executable will be installed /usr/sbin/nginx . The nginx configuration files will be installed in the /etc/nginx .
After the installation of Nginx, an administrator can start, stop and restart the server as well as configure the web server to begin serving web sites. To start, stop and restart Nginx the following commands are used. These commands should work on Debian and Red Hat based Linux distros.
$ service nginx start
$ service nginx stop
$ service nginx restart
To setup the reverse proxy for a given site, an upstream configuration needs to be added.
upstream <upstream name> {
server <ip address or domain name>:<port number>;
server <ip address or domain name>:<port number>;
keepalive 8;
}
The upstream configuration lists the available servers for handling requests from the reverse proxy. Depending upon the configuration, Nginx will load balance the incoming requests across the servers, handle failure conditions, etc..
Within a site's server configuration, the following settings need to be applied.
location / {
proxy_set_header X-Real-IO $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass <upstream name>;
proxy_redirect off;
}
A complete site configuration file would look something similar to this.
upstream node_server {
server <first node server ip address>:<first node server port>;
server <second node server ip address>:<second node server port>;
keepalive 8;
}
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name <some domain name>;
location / {
proxy_set_header X-Real-IO $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://node_server;
proxy_redirect off;
}
}
When setting up Express behind a proxy like Nginx, the Express application needs to be configured to trust the X-Forwarded-For header. To enable Express to trust the proxy header, add the following code to the Express application.
app.enable('trust proxy')
Depending upon the Linux distro you are using there may or may not be firewall rules configured on the server. Ubuntu 14.04 LTS does not install a firewall by default; therefore, one should be configured.
CentOS version 7 comes with a firewall configures with IP Tables. To open port 80 for HTTP and port 443 for HTTPS, the following IP Tables command should be executed.
iptables -A IN_public_allow -p tcp --dport 80 -j ACCEPT
iptables -A IN_public_allow -p tcp --dport 443 -j ACCEPT
Be sure only to open the ports being serviced by Nginx. The ports connecting to the Node.js Express web server directly should be block from outside access by the server and made available within the local network accessible by Nginx.
Once the Node.js web server has been configured and is running, loading testing tools can be used to test the availability of the web server under load. There are numerous tools available, for this course, we will be using a tool named Siege available from the web site http://www.joedog.org/siege-home/ . Siege can be installed using the Debian and Red Hat based package management systems.
For Debian based Linux distros.
$ apt-get install -y siege
For Red Hat based Linux distros.
$ yum install -y siege
Once siege is installed, we can load test a web site using the following command.
$ siege -c50 -t30s http://<some ip address or domain name>
With these options, siege will fire up 50 connections and hammer the server for 30 seconds. To run the load test for a full minute modify the option -t30s and change it to -t1m . When the load test is complete a report similar to this one will be shown.
** SIEGE 3.0.5
** Preparing 50 concurrent users for battle.
The server is now under siege...
Lifting the server siege... done.
Transactions: 2098 hits
Availability: 100.00 %
Elapsed time: 29.01 secs
Data transferred: 0.02 MB
Response time: 0.08 secs
Transaction rate: 72.32 trans/sec
Throughput: 0.00 MB/sec
Concurrency: 5.51
Successful transactions: 2098
Failed transactions: 0
Longest transaction: 3.05
Shortest transaction: 0.03
Transactions are the number of times requests are made from the server. This number divided by the number of connections will give you the number of times each connection made a server request.
Availability is the percent of transactions that were successful.
Elapsed time is the length of time the loading testing process ran for.
Data transferred is the amount of data transferred to all of the clients during testing.
Response time is the average response time to each client for all of the requests.
Transaction rate is the average number of transactions per second the server handled.
Throughput is the average number of bytes that were transferred to each client per second during testing.
Concurrency is the average of simultaneous connections. The higher the number, the worse the performance of the server.
Successful transactions are the number requests that received a response with a status code below 400.
Failed transactions are those requests which a response with a status code of 400 and greater.
Longest and shortest transactions are the number of seconds to complete the longest and short transaction.
In terms of raw performance for handling request that execute Node.js code, both options are very effective. Simply, there is no clear winner in terms of raw speed. Nevertheless, Nginx is most likely a better choice because of the ability to cache and serve static content, configure SSL, as well as, support other non-Node.js web sites on the same server. Additionally, Nginx can throttle connections and is most likely more reliable and stable than a simple Node.js process running Express.
With Nginx publicly facing the clients, how should the Node.js processes running Express behind the scenes be configured? Should the cluster module be used and have multiple processes running on one port or should multiple processes be started on multiple ports and rely up Nginx to do the load balancing? Regardless of the Node.js configuration, if multiple upstream servers are specified in the Nginx site configuration then Nginx will always be performing some kind of load balancing. If Nginx is going to load balance anyway, then there is no need to load balance twice both on the Nginx and Node.js Cluster ends. Therefore, it is best to let Nginx load balance and run each Node.js process independent of the other on its own port without using the Cluster module.
There are several options to keeping Node.js running when processes fail. An older but popular option, is the use of the forever Node.js package. A newer, growing in popularity approach, is to use Ubuntu's Monit and Upstart Linux packages to monitor the Node.js server application to keep it running.
Forever is distributed as two Node.js packages named forever and forever-monitor . The second package, forever-monitor is only needed if forever is going to be used programmatically.
The forever package should be install globally because it will be used from the command line. To install forever , the following command should be executed from a terminal. On Linux and Mac OS X, root privileges will be needed.
npm install -g forever
Forever offers many commands to manage the continued execution and recovery of Node.js processes. To see a full listing of the commands, type the following command from a terminal.
forever --help
The best way to understand how forever works is to create test script that throws an error from which Forever can recover from and execute the script again. Create a new file named error.js , then add the following code to it.
console.log("running script...");
setTimeout(function() {
console.log("throwing error...");
throw Error("error occurred");
}, 2000);
From a terminal type the following command.
forever -m 5 error.js
This command will start the script error.js with Node.js. After two seconds, an error will be thrown and the script will terminate. Upon termination, Forever will attempt to restart the script. The restart process will occur up to 5 times because of the -m option.
When Forever executes, it writes files to the .forever in the executing user's home folder. To change the location of Forever's folder, set the FOREVER_ROOT environment variable to the desired path. Make sure the user executing Forever has read and write permissions to the folder.
Forever can also because within Javascript code as part of a Node.js application.
Monit and Upstart are applications that are installed on Ubuntu and can be used to monitor and start applications. Monit and Upstart are not limited to Node.js, they can be used with any kind of application. Nevertheless, on Ubuntu they have become a popular alternative to using Forever.
Upstart is installed as a part of the Ubunto distro. One some systems Monit may need to be installed using the following command.
$ apt-get install monit
To configure Upstart to launch a Node.js application, a configuration file needs to be created in the /etc/init folder. Create a new file named "webapp.conf", and add the following configuration to it.
description "name of your file"
author "your name"
start on (local-filesystems and net-device-up IFACE=eth0)
stop on shutdown
respawn # restart when job dies
respawn limit 5 60 # give up restart after 5 respawns in 60 seconds
script
exec sudo -u <user> /usr/local/bin/node <path to script>/webapp.js >> <path to logs>/webapp.log 2>&1
end script
After creating the Upstart configuration file, run the following commands to ensure the log file exists and is writable.
$ sudo touch <path to logs>/webapp.log
$ sudo chmod 775 <path to logs>/webapp.log
To start the new web application, type the following command in the terminal.
$ sudo service webapp start
To verify the web application is running use curl to retrieve the home page of the web application.
After Upstart is configured, then Monit needs to be configured. You will notice that Upstart does have respawn capabilities and you may question why Monit is needed. Upstart checks for the PID to see if a respawn is needed. While this is good, it is possible the process is still running but the application is not serving page requests. In such a situation, Upstart would fail to detect this situation because there would be a running process. Monit is used to actually ping the web application via HTTP to make sure it is still responding to requests.
To configure Monit, we first need to modify Monit's configuration before adding the configuration for the web application. Open the file /etc/monir/monitrc in a text editor and uncomment the following lines.
set httpd port 2812 and
use address localhost # only accept connection from localhost
allow localhost # allow localhost to connect to the server and
Save the file and close it. Restart the Monit process with following command.
$ sudo service monit restart
Finally, we need to create a Monit configuration file for the application. Create file named webapp.monitrc in the /etc/monit/conf.d folder. Add the following configuration to it.
start "/sbin/start webapp"
stop "/sbin/stop webapp"
if failed port <port number of web app> protocol HTTP
request /
with timeout 5 seconds
then restart
To start the Monit configuration for webapp , type the following command in a terminal.
$ sudo monit start webapp
Now Monit will be monitoring the webapp Upstart service. To view the status of Monit, type the following command in a terminal.
$ sudo monit status
To see Monit in action, simply kill the webapp Node.js process and check the Monit status every couple of seconds. First, it will fail, then you will see it restart and resume successful connections. The entire process can take a few minutes.
Grunt is a JavaScript Task Runner. Grunt provides a framework to configure and execute tasks using JavaScript. Grunt tasks are written as Grunt Plugins, configured with a file named Gruntfile.js, and then executed.
Grunt is distributed through two Node.js packages with the package ids: grunt and grunt-cli . The grunt package is installed locally as a development dependency within your Node.js project. The grunt-cli package is installed globally. The local package provides the core grunt functionality. The global package allows the grunt command to be executed from a terminal.
To install the local, core package, run the following command in a terminal from the main folder of your project.
$ npm install grunt --save-dev
To install the global, command line tool package, run the following command in a terminal from any folder on on your computer. For Mac and Linux computers, you will need to run the command as root.
$ npm install -g grunt-cli
To create Grunt tasks, a file named Gruntfile.js must be created in the project folder. At the top of the file add the following code.
module.exports = function (grunt) {
"use strict";
// task code will go here...
};
The grunt parameter refers to the local, core grunt NPM package.
The grunt file can be divided into two parts: configuration and tasks. Configuration is performed using the initConfig function.
grunt.initConfig({
webServer: {
port: 8080,
rootFolder: './www'
}
});
The initConfig function expects a JavaScript object that will contain properties that define configuration values for the grunt tasks.
To define a task the following
grunt.registerTask('default', 'Start a web server', function () {
// task code
});
The first parameter to registerTask is the name of the task. If the task is the default task, then the name default can be used. The second parameter is a short description of the task. Finally, the third parameter is a function that defines the task. The task can do anything the developer would like it to do.
To retrieve the configuration information defined with initConfig the config function is used. To retrieve the webServer configuration defined below the following code is used.
var webServerOptions = grunt.config("webServer");
// output 8080 to the console
console.log(webServerOptions.port);
To run the default task of the grunt file, simply type grunt on the command line and press enter.
grunt.registerTask('webserver', 'Start a web server', function () {
// task code here...
});
To execute a named task such as webserver listed above, execute the task with the following command.
$ grunt webserver
Also, Grunt allows the passing of arguments from the command line into a task. Updating the web server task to accept a port parameters allows the port number to be passed from the command line. The register task definition would be modified to look like this.
grunt.registerTask('webserver', 'Start a web server', function (port) {
// task code here...
});
When invoked from the terminal, the Grunt command to run the web server task with a specific port number has the following syntax.
$ grunt webserver:8080
Arguments passed in from the command line are colon delimited. In the case of a string value, the argument syntax is formatted like this.
$ grunt sometask:"Some Text Here..."
The string value is wrapped in quotes to allow for spaces in the string value.
Within Grunt tasks, a common operation is launch an external program. Here is some sample code demonstrating how to launch external programs.
var exec = require('child_process').exec;
var process = exec("ls -al", function(error, stdout, stderr) {
// do something once the process ends
});
When running grunt tasks, the task will end even if asynchronous operations are waiting to complete. The best example would be a web server. With a typical grunt task, if a web server is started, it will be stopped as soon as the grunt task completes. This is not desired since the web server needs to continue to run in order to handle requests. To keep a grunt task running indefinitely, the following function must be called in the grunt task.
this.async();
Step 1. From a terminal, change to the myproject folder.
Step 2. Create a new file named Gruntfile.js , add the following code to it. Copy and paste the code from this document being sure to actually review the code to understand what it is doing.
module.exports = function (grunt) {
"use strict";
grunt.initConfig({
browserify: {
js: {
src: 'app/js/app.js',
dest: 'dist/js/app.js'
}
},
watch: {
all: {
files: ['**/*.html', '**/*.css', '**/*.tpl'],
tasks: ['copy'],
options: {
spawn: false,
cwd: { files: 'app/' }
}
},
scripts: {
files: ['**/*.js'],
tasks: ['browserify','uglify'],
options: {
spawn: false,
cwd: { files: 'app/' }
}
},
angularjs: {
files: ['node_modules/angular/angular.min.js'],
tasks: ['copy'],
options: {
spawn: false,
cwd: { files: '/' }
}
},
less: {
files: ['**/*.less'],
tasks: ['less','cssmin'],
options: {
spawn: false,
cwd: { files: 'app/' }
}
}
},
copy: {
all: {
expand: true,
cwd: 'app/',
src: ['**/*.html', '**/*.css', '**/*.tpl'],
dest: 'dist/'
},
angularjs: {
expand: true,
cwd: 'node_modules/angular',
src: ["angular.min.js"],
dest: 'dist/js'
},
bootstrapcss: {
expand: true,
cwd: 'node_modules/bootstrap/dist/css',
src: ["*"],
dest: 'dist/css'
},
bootstrapfonts: {
expand: true,
cwd: 'node_modules/bootstrap/dist/fonts',
src: ["*"],
dest: 'dist/fonts'
}
},
less: {
development: {
options: {
paths:["app/less"]
},
files: {
"dist/css/app.css": "app/less/app.less"
}
}
},
cssmin: {
minify: {
expand: true,
cwd: 'dist/css',
src: ['*.css', '!*.min.css'],
dest: 'dist/css',
ext: '.min.css'
}
},
uglify: {
my_target: {
files: {
'dist/js/app.min.js': ['dist/js/app.js']
}
}
},
webServer: {
port: 8080,
rootFolder: './dist'
},
dbSqlLite: {
file: "lab.db"
}
});
grunt.loadNpmTasks("grunt-browserify");
grunt.loadNpmTasks("grunt-contrib-copy");
grunt.loadNpmTasks("grunt-contrib-watch");
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.event.on('watch', function(action, filepath, target) {
grunt.log.writeln(target + ": " + filepath + " has " + action);
});
// register a task to run the express server
grunt.registerTask('webserver', 'Start a web server', function () {
var
webServerOptions = grunt.config("webServer"),
dbSqlLiteOptions = grunt.config("dbSqlLite"),
webServer = require("./webServer");
// tells the task this will run async otherwise the task will
// end the web server when it completes this method
//this.async();
webServer(webServerOptions, dbSqlLiteOptions)
.start()
.then(function () {
grunt.log.writeln("Started connect web server on port " + webServerOptions.port);
grunt.log.writeln("ctrl+c to exit");
})
.catch(function (err) {
grunt.log.error(err.message || err);
});
});
grunt.registerTask('default', ['browserify', 'less', 'cssmin', 'copy', 'uglify', 'webserver', 'watch']);
};
Save the file, and close it.
Step 3. From the terminal, type the command grunt and press enter . This command fire up the default Grunt task. For this Grunt file, the default Grunt task will launch the web server, configure web sockets, initialize the database, as well as, setup file watchers to execute various development tasks related to packaging modules, compiling preprocessor code and performing file combination and minification.
Step 4. What is the difference between the app folder and the dist folder? What is the purpose of each?
Exercise Complete!
Grunt plugins allow developers to create generalized tasks that can be reused in many projects. Typically, Grunt plugins are distributed via NPM and contain logic to perform tasks using the configuration provided by the project that is including the plugin. Developing Grunt plugins is very simple to do.
First, create a folder named after your plugin. In this example, we will use the name mygruntplugin .
$ mkdir mygruntplugin
Change to the folder you created, then create a tasks folder.
$ cd mygruntplugin
$ mkdir tasks
Next, create a package.json file with npm init , answering the questions as appropriate.
$ npm init
At a minimum, add a local grunt Node.js package to the Grunt plugin package.
$ npm install grunt --save-dev
Then change to the tasks folder, and create a lib folder.
$ cd tasks
$ mkdir lib
The lib folder will contain all of the modules of library code that perform the actual task operations. The tasks folder is for wiring up the code modules in the lib folder to the named Grunt tasks. Change to the lib folder, create a new file named mylib.js , then add the following code to the file.
module.exports = (function() {
"use strict";
return function() {
return {
log: function(prefix, message) {
console.log(prefix + "=> " + message);
}
};
};
}());
This module returns a function object that when invoked returns a custom console logger that allows each log message to prefixed with a message identifier.
To wire this code up to a Grunt task, change to the parent tasks folder, create a new file named mytask.js , then add the following JavaScript code to the file.
module.exports = (function() {
"use strict";
var myLib = require("./lib/mylib.js");
return function(grunt) {
grunt.registerTask("atask", "A sample task", function() {
myLib().log("MyApp", "sample task");
});
};
}());
This code, wires up the module in the lib folder to a named Grunt task. The final step to creating the plugin is to create Gruntfile.js for the plugin. Change to the root package folder, create a file named Gruntfile.js , then add the following code it.
module.exports = (function() {
"use strict";
return function(grunt) {
grunt.loadTasks("tasks");
};
}());
The Gruntfile.js loads the named Grunt tasks from the tasks folder and makes them available to Grunt in the packages that install this plugin package.
To test the Grunt plugin, simply use the NPM package linking (described earlier) to link this package to the project package you are currently working on. Then include the tasks in this Grunt plugin in the Gruntfile.js of the project package like this.
grunt.loadNpmTasks('mygruntplugin');
Then reference a task from the Grunt plugin as shown here.
grunt.registerTask('mytask', 'My Task', ['atask']);
Save the project package's Grunt file, and run the following from the terminal.
$ grunt mytask
The output will be the prefixed console log message that was coded in the Grunt plugin.
Running "atask" task
MyApp=> sample task
Done, without errors.
Creating Grunt plugins is very simple and allows for the creation of helpful and sophisticated tasks to be shared among many projects and even publicly distributed.
Copyright 2015, Eric W. Greene. All Rights Reserved.


Hash Example
What is a Hash? It is a Ruby object that stores information in pair with a key=>value structure.
Here is an example of a Hash in Ruby.
line 4 is where we declare the Hash, named foods
To the left of the hash rocket, => symbol are the keys
To the right of the => symbol are the values. In this case, the values are actually stored in an [array].
Hash Methods
How would you display just the keys in a Ruby Hash?
On line 12 we define the method name and we want to pass the hash name over as an (argument)
We are interested in just the keys of the hash so we can use the each_key method to display just keys
How would you display just the values in a Ruby Hash?
Very similar concept, we define the method in line 21 with the hash name as the (argument)
Outcome of the Hash
We can call the function by simple typing the function name and passing the name of the hash we want to use: food_type(foods)
Because we are using puts, each key will be displayed in a separate link:
Italian
Chinese
American
----------------------------------------------------------
After we call the function to display just the values of the hashfood_items(foods)
Here is the output of values from our foods hash example
chicken parmesan
pasta
pizza
kung pao chicken
orange chicken
spring rolls
dim sum
fries
burgers
hot dogs


{% extends "page_with_title_and_lede.html" %} {% load i18n %} {% block head_title %}Become a Sponsor{% endblock %} {% block heading %}Become a Sponsor{% endblock %} {% block body_class %}sponsors{% endblock %} {% block lede %} Your generous support builds careers, brings students together with expert developers, and promotes free and open source software. How can we help you? Explore our prospectus. {% endblock %} {% block content %}
Our base costs, including our venue, printing, web hosting, and more, are all funded through sponsorship. In return, we offer complimentary corporate level tickets, a chance to talk about your company on our main stage, floor space in the lobby to display your free-standing banners, and as much praise as we can deliver in front of 400 grateful Pythonistas.
Below is an overview of sponsorship levels. Please email us for more information.
Package sponsorships are the widest-reaching and best value sponsorships we offer at North Bay Python. When our attendees arrive at the venue, they'll see your signage as they walk through the door. As they're sitting in the theatre, they'll see your logo on the backdrop behind the speakers, and on-screen on between talks. You'll also get the chance to present a short talk about your organization between two of our invited presentations.
If you're looking for something a bit more exclusive, North Bay Python's À la Carte sponsorships allow you to promote your organization as part of an important offering during the conference, including lanyards, catering, or video branding. We'll also recognize you as a Silver package sponsor, with the opportunity for discounted upgrades to higher package tiers.
Sponsorship can also be in the form of in-kind donations of goods and services essential to organizing the conference, or in assisting speakers to attend the conference. If you can make a substantial in-kind donation, we will recognize you as a package-level sponsor of equivalent value.
Community groups, such as Python Meetups and PyLadies groups, are the lifeblood of the Python community, and we need your help to put on the best conference we can. If you can help us with one of the following, we'll recognize you as a community partner, which comes with all of the benefits of a Silver sponsorship.


Five things I miss in Instagram
Instagram is one of those social networking apps that really stuck to me. I usually try one out but quickly remove it again when it doesn't immediately appeal to me. It took me ages before my friends finally convinced me to use Snapchat and I'm still not overly fond of it even though I regularly use it these days.
But not Instagram. I check it multiple times a day and regularly use it. I mostly use it privately with friends and family. Because I use it so much I'm noticing some of Instagram's shortcomings. Things where the service is lacking and where it can definitely be improved. Below is a list with five of the things I miss most in Instagram.
Multiple accounts
This is probably the most obvious one. I'm currently using a private account to share with just friends and family but I wouldn't mind having a public account so I could share photos publicly as well. If I wanted to do this now I would constantly have to log out and in again in order to switch accounts. This is pretty inconvenient.
I know some of my friends which run businesses and who use Instagram as a primary medium for their business. They already have multiple accounts, some of them even up to 6 different accounts. Even though tools like 1Password make it easy for us to remember passwords these days, it's still quite a hassle to switch accounts by logging out and in every time.
This is definitely the thing which ranks highest on my list of features I want for Instagram.
Photo and video visibility
Even better would be if I could share my photos or videos publicly or with just friends. The same way Facebook does actually. That would even take away the need for me to manage multiple accounts.
Instagram already has a feature called "Instagram Direct" so you can send photos to specific friends only, kind of like the way Snapchat does. But I rarely use the feature and it doesn't allows me to send to all my friends at once with a single button. A public/friends option would be great.
 When trying to change your profile picture you have a wide arrange of options: using your Twitter or Facebook picture, importing one from your device or taking a new one.
But you cannot use one of your own photos. This strikes me as bizarre and plainly illogical. A photo service which doesn't allows you to use one of the apps photos as your profile picture.
What's more is that I cannot even download my own photo to my device in order to use the import feature to set it as a profile picture. I'd have to take a screenshot, crop the picture and import it. Why cannot I download my pictures? I took them, they belong to me.
Better notifications
Instagram is seriously lacking on the notifications part. For instance, in the iOS app, the app isn't even using the badge counter functionality. I'd have to go into the app and check my notifications manually to see if there were new ones.
Also, the fact that you have to mention someone in a comment thread they're participating in, to let them know you're talking to them is pretty tiresome. Why can't you be automatically subscribed to comment threads when you post a comment? It would be great if that was a preference. You could even have options like "get notifications for all comments" and "get notifications only from original poster" if you just want to know when the original poster replied. Now if you talk to someone but forget to mention them, chances are likely that they'll never know you said something to them.
Lists
This is a feature which Twitter makes great use of. I can follow only the people I want for my main timeline and use lists to keep track of everything else. It would be great if Instagram had a likewise feature where I could group certain accounts in lists and change the list I'm looking at from the top navigation bar. This in combination with private/public lists would allow for some great new Instagram functionality.
Conclusion
But of course Instagram is already a great service, one which I use daily. It's easy to take a picture or video of something you're doing or seeing at the moment and share it with all of your friends immediately. The fact that it's a separate app from Facebook is a plus because it takes away all of the noise which sometimes clutters the Facebook app. But there's room for improvement. Starting with any of the five points above. I hope Instagram will address these one day.


A-Blog
Home
About
Profile
Register
Hottest News Coming!!
Our Sidebar
You find latest news blog and many more information here.
Top News
Latest post
Annoucement
Calender


Spark is a Firebase-hosted Flask app running on a Docker served by
Google Cloud. It employs Cloud Firestore and Realtime Database to store
information pertaining to users. Spark was created because we, RGBHack,
(a team of high school students) noticed the need for a platform that
could bring increased productivity to teams during the quaratine due to
COVID-19. This project is open source, so you can learn more by
visiting our
GitHub Repository.


GOOGLE SAYS THANKS TO ALL THE HELPERS THROUGH ITS DOODLE : COVID 19A THANK YOU BY GOOGLE IN ITS OWN
The coronavirus has created a havoc in the recent times and the whole world is fighting unitedly against it. People across the world are staying indoors, working from home while schools, colleges and most offices are shut. Yet there are many people who are risking their lives and thriving hard for the best. Today, the doodle that Google shared was a compilation of all those doodles, thanking all the people who are at the forefront fighting Covid-19 . Google here takes a chance in appreciating these people who are helping , guiding , struggling in these difficult times. Google has done it in its own style by doing a beautiful doodle.
These people involve healthcare workers, sanitation workers, farmers, food service workers, the police officials, the firemen, people helping with public transportation, packing, shipping and delivery people as well.This illustration mostly depicted all the people engaged in the essential services who are out of their homes yet without a complaint carrying out their duty in concern with love of the world. It has also illustrated those helpers like teachers and professors who are taking classes, lectures ,demonstrations through video calls in response to avoid educational downfall.
These people involve healthcare workers, sanitation workers, farmers, food service workers, the police officials, the firemen, people helping with public transportation, packing, shipping and delivery people as well. Actually, Google has been doing these doodles and expressing their gratitude through art, but this doodle does not leave behind any of the essential services. We also thank all these people from bottom of our hearts and wish you all a happy quarantine with lots of health and hygiene. Stay safe. Help the world. #google #socioad #digitalmediaupdates


Woman's body found in Quebec residence after husband turns himself in to police
SALABERRY-DE-VALLEYFIELD, Que. — A Quebec woman is dead and her husband is in custody following an alleged domestic violence incident southwest of Montreal.
by Canadian PressSALABERRY-DE-VALLEYFIELD, Que. — A Quebec woman is dead and her husband is in custody following an alleged domestic violence incident southwest of Montreal.
The 38-year-old man was arrested Saturday afternoon after he presented himself at a Montreal police station, where authorities allege he admitted to having assaulted his wife.
The local authorities contacted provincial police, who discovered the body of a 48-year-old woman in a residence in Salaberry-de-Valleyfield, Que.
Police say it's unclear how long the woman had been dead, and their investigation is on-going.
The man is expected to appear in court on Monday.
This report by The Canadian Press was first published Nov. 17, 2019.
The Canadian Press


Dr. Beverly Crusher, MD
Specialty
Internal Medicine and Pediatrics
Location
Cleveland General Hospital
Insurance Accepted
Blue Cross, Cigna, and Shield
Languages
English and Spanish
Accepting New Patients
Yes
Available Dates
Sun
Mon
Tue
Wed
Thu
Fri
Sat
Available Time Slots
9:00 AM
10:00 AM
11:00 AM
12:00 PM
1:00 PM
2:00 PM
3:00 PM
4:00 PM
5:00 PM
Reason for Appointment
Max 200 Characters


projects
about
contact
Hello World
John Doe
I am a web developer
projects
Bulb light website
Helcio's github
Soumik's github


- Parameters
-
| EventDispatcherInterface | $dispatcher | An EventDispatcherInterface instance |
| ContainerInterface | $container | A ContainerInterface instance |
| ControllerResolverInterface | $controllerResolver | A ControllerResolverInterface instance |
| RequestStack | $requestStack | A stack for master/sub requests |
Definition at line 41 of file ContainerAwareHttpKernel.php.
The documentation for this class was generated from the following file:


{% load humanize %}
Total invoiced for {{ month }}: ${{ monthly| intcomma }}
Total invoiced to date for {{year}}: ${{ yearly| intcomma }}
Projected revenue for {{ year }} is ${{ revenue_projection|intcomma }}
{{ date.0 }} projects to reach its {{date.3}} budget on {{ date.1 }}
{% endfor %}


Imagine-a-Company
Do whatever you want when you want to.
Breaking The Grid, Grabs Your Attention
Instead of focusing on content creation and hard work, we have learned how to master the art of doing nothing by providing massive amounts of whitespace and generic content that can seem massive, monolithic and worth your attention.
Read MoreCase Studies
Did We Tell You About Our Bananas?
Yes I know you probably disregarded the earlier boasts as non-sequitur filler content, but its really true. It took years of gene splicing and combinatory DNA research, but our bananas can really dance.
I'm Still Quite Interested


Hello, my name is Ewelina.
I enjoy building websites. I am a passionate learner and problem solver, eager to explore new languages and frameworks and learn with like-minded individuals. If you are an employer looking to hire, you can get in touch with me.
See my GitHub Download my CVWELCOME IN
A fun and accessible questionnaire for children (age 5-12) when first visiting Child and Adolescent Mental Health Services (CAMHS).
BIG BUS TOURS
I worked with a front-end lead developer, the UX team and designers to develop a fully responsive, multi-language, multi-currency Big Bus Tours' website on Magento 2.
CONTACT LIST
Simple CRUD contact list (side project). The main reason for building this project was to gain experience using AngularJS and learn end-to-end testing.


Rahul Kumar Gupta
<EMAIL_ADDRESS>RahulGuptaNitro
rahul-k-gupta
Computer Science Enthusiast, always ready to explore the new elements of computer engineering.
Hi


Welcome to THE food voting website by EatBeansFromACan.org, the world's leading authority on selecting foods that taste great!
Please highlight one of the folowing two images, then click the "Vote" button


Store Manager
Welcome to
storename
store description
Edit
Inventory
Name
Price
Delete
Item Name:
Price:


Object Property: 'is condition of'
http://purl.org/biotop/btl2.owl#isConditionOf
Annotations (2)
-
definition "'has condition' (inverse 'is condition of')
connects exclusively situations (temporal slices of lives) with conditions as present during the whole extent of the corresponding situation" ()
-
label "is condition of" ()
Inverses (1)
Usage (3)


Automatically finds and parses any Microformat, Structured Data or natural language events from web content for your calendar


📕Bookmarks📗
Ya got too many tabs open! Put stuff here to check out later:
Paste link here:
Description (optional):
Your list:
📗 A blog post on how I made this site! 📕
Copyright (c) 2020 DaveyDevs
MIT License