Modularizing your JavaScript development

Param Singh
Agenda
- What is NPM?
- Module Resolution
- package.json
- Semantic Versioning
- npm cli
- Publishing to NPM
- Questions
NPM (Node Package Manager)?
npm makes it easy for JavaScript developers to share and reuse code, and it makes it easy to update the code that you're sharing”
• Tool that automates the process of installing, uninstalling and updating software packages
• Provides a standard way of managing dependencies
• Managing files manually is an extremely errorprone task
Good artists copy; great artists steal - Pablo Picasso.
Using NPM
- Initialising a project with npm init
- package.json would be created
- Install dependencies using
npm i packageName@version --save
// or
npm i packageName@version --save-dev
Package vs Module
A package is any of:
- a) a folder containing a program described by a package.json file
- b) a gzipped tarball containing (a)
- c) a url that resolves to (b)
- d) a <name>@<version> that is published on the registry with (c)
- e) a <name>@<tag> that points to (d)
- f) a <name> that has a latest tag satisfying (e)
- g) a git url that, when cloned, results in (a).
- A folder with a package.json file containing a main field.
- A folder with an index.js file in it.
- A JavaScript file.
A module is any of:
Dependency Tree
Dependency Hell

Imagine there are three modules: A, B, and C. A requires B at v1.0, and C also requires B, but at v2.0. We can visualize this like so:
Dependency Hell
Now, let's create an application that requires both module A and module C.

Dependency Hell
A package manager would need to provide a version of module B. In all other runtimes prior to Node.js, this is what a package manager would try to do. This is dependency hell:

How NPM 2 Works?
Imagine there are three modules: A, B, and C. A requires B at v1.0, and C also requires B, but at v2.0. We can visualize this like so:

How NPM 2 Works?
Now, let's create an application that requires both module A and module C.

How NPM 2 Works?
Instead of attempting to resolve module B to a single version, npm puts both versions of module B into the tree, each version nested under the module that requires it.


How NPM 3 Works?
- npm3 tries to mitigate the deep trees and redundancy that such nesting causes.
- Installs some secondary dependencies (dependencies of dependencies) in a flat way
Imagine we have a module, A. A requires B.

How NPM 3 Works?
- Now, let's create an application that requires module A.
- On npm install, npm v3 will install both module A and its dependency, module B, inside the /node_modules directory, flat.
In npm v2 this would have happened in a nested way.

How NPM 3 Works?
Another module C requires B, but at another version than A.

How NPM 3 Works?
Since B v1.0 is already a top-level dep, we cannot install B v2.0 as a top level dependency. npm v3 handles this by defaulting to npm v2 behavior and nesting the new, different, module B version dependency under the module that requires it -- in this case, module C.


NPM 3 Duplication

NPM 3 Duplication
Module D depends on Module B v2.0, just like Module C.

- Because B v1.0 is already a top-level dependency, we cannot install B v2.0 as a top level dependency.
- Therefore Module B v2.0 is installed as a nested dependency of Module D, even though we already have a copy installed, nested beneath Module C.

NPM 3 Duplication
However, if a secondary dependency is required by 2+ modules, but is installed as a top-level dependency in the directory hierarchy, it will not be duplicated, and will be shared by the primary dependencies that require it.
- Module E, like Module A, depends on Module B v1.0.



NPM 3 Duplication
Module A to v2.0, which depends on Module B v2.0, not Module B v1.0?

NPM 3 Duplication

NPM 3 Duplication
Update Module E to v2.0, which also depends on Module B v2.0 instead of Module B v1.0, just like the Module A update.



NPM 3 Duplication
We have Module B v2.0 in nearly every directory. To get rid of duplication, we can run:
npm dedupe


NPM 3 Non Determinism

- npm3 does not install dependencies in a deterministic way.
- your local node_modules directory will differ from both your coworkers' node_modules directories, as well as the node_modules directories on your staging, testing, or production servers.
NPM 3 Non Determinism

NPM 3 Non Determinism
{
"name": "example3",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"mod-a": "^1.0.0",
"mod-c": "^1.0.0",
"mod-d": "^1.0.0",
"mod-e": "^1.0.0"
}
}
NPM 3 Non Determinism
Updated Module A to v2.0


NPM 3 Non Determinism
Now, package.json looks like
{
"name": "example3",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"mod-a": "^2.0.0",
"mod-c": "^1.0.0",
"mod-d": "^1.0.0",
"mod-e": "^1.0.0"
}
}
NPM 3 Non Determinism
Running npm install in another system

package.json

Semantic Versioning
(SemVer)
What is SemVer?
- SemVer is a 3-component system in the format of x.y.z where:
- x stands for a major version
- y stands for a minor version
- z stands for a patch
- So you have: Major.Minor.Patch.

- SemVer is a standard that a lot of projects use to communicate what kinds of changes are in this release.
- It's important because sometimes those changes will break the code that depends on this package.
- It let the users know the level of effort it's going to take for them to update to the latest version.
Patch
- Changes added doesn't not break anything.
- And it doesn't add any new features
- Potentially a bug fix

Minor Release
- Changes added adds new features.
- And it doesn't break things. Existing functionality is intact.
- Adding a new method or optional arguments.

Major Release
- Changes added adds new features or modified existing ones.
- And it does break things.
- Not backward compatible.

Usage of SemVer
-
The way that you'll use semantic versioning as the user of a package is to specify which kinds of updates you want to accept.
Accepting Patches Only
-
You don't want any changes to the api to be included in the updates that you're bringing down.


Accepting Minor Only
-
You don't want any breaking changes.


Modules Resolution
Module Loading Strategy
Whenever you require()a module, the following steps are executed in order:
1. If it is a core module like http, fs, path etc, load the core module.
2. If it is a relative path, load the module from the relative path.
3. Look for the module in the ./node_modules directory. If it is not there, recursively search in the parent directories’ ./node_modules until either the module is found or the root of the file system is reached.
npm link
- It allows you to load a module from anywhere on your system.
- To Symlink a package folder
From the source package directory:
npm link
In your consumer project directory:
npm link <package-name>
How it works?
-
It creates two Symbolic Links:
-
Global Symlink
- When you run npm link in a module’s root directory, npm creates a symbolic link from your “global node_modules” directory to the local module’s directory.
- The “global node_modules” directory is a special directory where all modules installed with npm install -g are stored
-
Local Symlink
- When you run npm link <module_name> in a project’s directory, npm creates a symbolic link from ./node_modules/<module_name> to <global_node_modules>/<module_name>
-
Global Symlink

Publishing package to NPM
- Login into the command line using npm login.
-
Commit changes and Bump the package semantic version number using
- npm version patch
- npm version minor
- npm version major
- Run npm publish



Questions
Thank You!
@paramsingh_66174

NPM
By Param Singh
NPM
- 740