Introduction to NPM

What is NPM?

NPM stands for Node Package Manager, and is the default way to extend your Node applications.

There are an absolute ton of packages available to install and use immediately, making NPM wildly popular for software developers.

What is Node?

Node.js, or often simply just Node, is a Javascript runtime environment that allows Javascript code to be executed outside of the web browser.

It first came about in 2009 when the creator (Ryan Dahl) took Google’s V8 Javascript Engine which powers its Chrome browser, and repurposed it. Adding in additional logic allowing it to be used independently to execute Javascript on the server.

This opened up a whole new world for frontend Javascript developers to start writing code for the backend. Many of these developers are called Full-Stack Javascript Developers now.

How to setup an NPM project

While NPM is a command-line (CLI) tool, it’s registry is available online at npmjs.com.

It’s very easy to search for packages directly from the website, before installing them locally.

In order to illustrate things better, let’s create an NPM Project and play around a bit with the package manager.

If you don’t have npm or node installed, then take a look here for a quick setup. Alternatively, download node here.

First, we need to make sure we have a directory to work in. Let’s create one and move into there.

mkdir -p ~/src/tutorials/npm_testing
cd $_

Great, now we will have to run npm init to initiate an NPM project.

$ npm init

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (npm_testing)

We will now be asked to customise our application, but we’re happy with all the default for now, so just press Enter at each of the prompts for now.

$ npm init

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (npm_testing)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /Users/ao/src/tutorials/npm_testing/package.json:

{
  "name": "npm_testing",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this OK? (yes) yes

If you want to do this quickly next time, you can always just pass the -y flag to npm init and you won’t be prompted for any inputs.

$ npm init -y

Wrote to /Users/ao/src/tutorials/npm_testing/package.json:

{
  "name": "npm_testing",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}


   ??????????????????????????????????????????????????????????????????
   ?                                                                ?
   ?       New minor version of npm available! 6.4.1 ? 6.13.7       ?
   ?   Changelog: https://github.com/npm/cli/releases/tag/v6.13.7   ?
   ?               Run npm install -g npm to update!                ?
   ?                                                                ?
   ??????????????????????????????????????????????????????????????????

So what has really been created now?

Let’s take a look in the directory, issue the ls command and you will see a new file called package.json. If we cat this file, we see the following output:

{
  "name": "npm_testing",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

We now need a file called index.js as highlighted under the main key. You can change this to anything you like, but these defaults are fine for us at the moment.

Run touch index.js from the CLI to create the new file.

At this stage we opt to open our project directory in a code editor, my chosen one at the moment is Visual Studio Code. There is a command-line alias available that allows me to execute the command code . in the directory I want to open to load the project in vscode.

Now we can start writing some NodeJS code and make use of an NPM module.

Let’s put the following code in our index.js file:

const request = require('request');

request('https://ao.gl', { json: false }, (err, res, body) => {
  if (err) { return console.log(err); }
  console.log(body.url);
});

If we try to run this from the CLI, we are greeted by some errors:

$ node index.js

internal/modules/cjs/loader.js:583
    throw err;
    ^

Error: Cannot find module 'request'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
    at Function.Module._load (internal/modules/cjs/loader.js:507:25)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at Object.<anonymous> (/Users/ao/src/tutorials/npm_testing/index.js:1:79)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)

This is because we don’t have the request package available for use yet.

It is an easy fix, all we need to do is issue the npm install request command. (npm i request for short)

$ npm i request

npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN [email protected] No description
npm WARN [email protected] No repository field.

+ [email protected]
added 48 packages from 59 contributors and audited 63 packages in 3.773s
found 0 vulnerabilities

Now let’s try and run node index.js once more.

$ node index.js

undefined

No errors this time, great! But we get an undefined response. Let’s fix that quickly. Update our code:

const request = require('request');

request('https://ao.gl', { json: false }, (err, res, body) => {
  if (err) { return console.log(err); }
  console.log(res.statusCode, body.length);
});

And run it again:

$ node index.js

200 129761

We printed out 2 values, firstly the status code of the request, followed by the length of the HTML body we got back.

NPM Modules Directory

NPM stores everything in a local directory called npm_modules.

$ ls -lp

total 48
-rw-r--r--   1 ao  staff    189  ... index.js
drwxr-xr-x  50 ao  staff   1600  ... node_modules/
-rw-r--r--   1 ao  staff  13120  ... package-lock.json
-rw-r--r--   1 ao  staff    275  ... package.json

If we take a look in the node_modules directory we will see all the recursive dependencies our project needs.

$ ls -lashp node_modules

total 0
0 drwxr-xr-x  50 ao  staff   1.6K  ... ./
0 drwxr-xr-x   6 ao  staff   192B  ... ../
0 drwxr-xr-x   6 ao  staff   192B  ... .bin/
0 drwxr-xr-x   9 ao  staff   288B  ... ajv/
0 drwxr-xr-x   6 ao  staff   192B  ... asn1/
0 drwxr-xr-x   7 ao  staff   224B  ... assert-plus/
0 drwxr-xr-x  12 ao  staff   384B  ... asynckit/
0 drwxr-xr-x   6 ao  staff   192B  ... aws-sign2/
0 drwxr-xr-x   8 ao  staff   256B  ... aws4/
0 drwxr-xr-x   7 ao  staff   224B  ... bcrypt-pbkdf/
0 drwxr-xr-x   7 ao  staff   224B  ... caseless/
0 drwxr-xr-x   7 ao  staff   224B  ... combined-stream/
0 drwxr-xr-x   8 ao  staff   256B  ... core-util-is/
0 drwxr-xr-x   8 ao  staff   256B  ... dashdash/
0 drwxr-xr-x   8 ao  staff   256B  ... delayed-stream/
0 drwxr-xr-x   8 ao  staff   256B  ... ecc-jsbn/
0 drwxr-xr-x  12 ao  staff   384B  ... extend/
0 drwxr-xr-x  11 ao  staff   352B  ... extsprintf/
0 drwxr-xr-x  10 ao  staff   320B  ... fast-deep-equal/
0 drwxr-xr-x  13 ao  staff   416B  ... fast-json-stable-stringify/
0 drwxr-xr-x   6 ao  staff   192B  ... forever-agent/
0 drwxr-xr-x   8 ao  staff   256B  ... form-data/
0 drwxr-xr-x   8 ao  staff   256B  ... getpass/
0 drwxr-xr-x   6 ao  staff   192B  ... har-schema/
0 drwxr-xr-x   6 ao  staff   192B  ... har-validator/
0 drwxr-xr-x  10 ao  staff   320B  ... http-signature/
0 drwxr-xr-x   7 ao  staff   224B  ... is-typedarray/
0 drwxr-xr-x  10 ao  staff   320B  ... isstream/
0 drwxr-xr-x   9 ao  staff   288B  ... jsbn/
0 drwxr-xr-x  13 ao  staff   416B  ... json-schema/
0 drwxr-xr-x   9 ao  staff   288B  ... json-schema-traverse/
0 drwxr-xr-x  10 ao  staff   320B  ... json-stringify-safe/
0 drwxr-xr-x   8 ao  staff   256B  ... jsprim/
0 drwxr-xr-x   8 ao  staff   256B  ... mime-db/
0 drwxr-xr-x   7 ao  staff   224B  ... mime-types/
0 drwxr-xr-x   6 ao  staff   192B  ... oauth-sign/
0 drwxr-xr-x  11 ao  staff   352B  ... performance-now/
0 drwxr-xr-x   9 ao  staff   288B  ... psl/
0 drwxr-xr-x   7 ao  staff   224B  ... punycode/
0 drwxr-xr-x  12 ao  staff   384B  ... qs/
0 drwxr-xr-x   9 ao  staff   288B  ... request/
0 drwxr-xr-x   7 ao  staff   224B  ... safe-buffer/
0 drwxr-xr-x   9 ao  staff   288B  ... safer-buffer/
0 drwxr-xr-x  10 ao  staff   320B  ... sshpk/
0 drwxr-xr-x   7 ao  staff   224B  ... tough-cookie/
0 drwxr-xr-x   6 ao  staff   192B  ... tunnel-agent/
0 drwxr-xr-x  14 ao  staff   448B  ... tweetnacl/
0 drwxr-xr-x  11 ao  staff   352B  ... uri-js/
0 drwxr-xr-x  14 ao  staff   448B  ... uuid/
0 drwxr-xr-x   9 ao  staff   288B  ... verror/

It is very important to never commit this node_modules directory to your SVN, such as Github.

Using git, we can avoid this by adding the directory to the project’s .gitignore file.

echo node_modules >> .gitignore

Closing remarks

NPM is a powerful package manager that gets you up and running quickly.

Writing Javascript Node applications has never been easier, as there are a plethora of community crafted packages available to use for free.

The node_modules directory can really get out of hand and is often massive for larger projects. Never ever commit it to Github and always run a fresh npm i when cloning a Node project locally.

0 0 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments