Proper handling of javascript dependencies allows every team member to use the same library versions during project development. Keeping them consistent prevents many elusive errors and can be easily achieved with npm.
Requirements
You will need npm, the Node package manager, installed on your local machine. The nodejs package contains the nodejs binary as well as npm, but the version of the latter can be a little behind the latest available. It is considered good practice to install the most recent npm version separately. To see whether you already meet those prerequisites, run in your command line:
1 2 |
$ nodejs -v $ npm -v |
If they are not present, run:
1 2 3 |
$ sudo apt update $ sudo apt install nodejs $ sudo apt install npm |
Shall you need to, check out other resources for more detailed information and alternative options to install nodejs
and npm
on Ubuntu.
Manage npm modules
To organize external javascript libraries, we need to keep all information required to download them in our repository. This will allow every team member to build the application with the same dependencies. It is attainable thanks to the package.json file which can be easily generated from your command line.
If you are using a framework, check out its documentation to see where the package.json file should be stored. |
In this example, we are managing assets in a Spring Boot
application and this framework uses the static
directory to store all static resources. Go to it’s location:
1 |
$ cd src/main/resources/static/ |
Run
$ npm init --yes to create the default package.json
file. In case you want to specify some information about your project, just run the command without the --yes
flag, so you can answer questions from the questionnaire:
1 2 3 4 5 6 7 8 9 10 11 |
$ npm init Press ^C at any time to quit. name: (static) springboot-todo version: (1.0.0) description: entry point: (index.js) test command: git repository: keywords: author: license: (ISC) |
You can find an explanation to every attribute in the npm documentation.
An example file structure:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "name": "springboot-todo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "little_pinecone", "license": "ISC", "devDependencies": { } } |
Libraries required during the development process can be included with $ npm install --save-dev package_name, those needed on a production environment are installed simply by typing $ npm install package_name .
Use SemVer notation to control versions consciously
This notation separates changes in a library lifetime into three categories: major, minor and bug fixes. By suffixing a required version with ^
or ~
you can regulate which improvements will be part of your project dependencies with every
$ npm install and
$ npm update .
You can specify allowed versions in the package.json
file with:
- ^4.5.1 – the update will install the newest release of the major version (4.*.*), which will introduce patches and new features but hold the backwards compatibility;
- ~4.5.1 – the update will install the newest release of the minor version (4.5.*), which will introduce just bug fixes;
- using npm range calcucator.
You can read more about SemVer in its documentation.
Commit only the files you need
The package.json
as well as package-lock.json
files should be commited. The latter can be created by running the following command in the directory which already contains the package.json file:
1 2 3 4 |
$ npm i --package-lock-only npm notice created a lockfile as package-lock.json. You should commit this file. npm WARN <span class="crayon-v">springboot</span><span class="crayon-o">-</span>todo@1.0.0 No description npm WARN <span class="crayon-v">springboot</span><span class="crayon-o">-</span>todo@1.0.0 No repository field. |
It contains information about specific version, location as well as requirements for every dependency given in the package.json
file. It also confirms the integrity of the installed dependecies with hashes. Thanks to all those data, the package-lock is the source of truth for javascript dependencies and every time someone installs them, the downloaded libraries will be exactly the same, despite the latest major or minor release available (remember the semver notation from above). This allows you to share unified dependencies across the team.
In contrast, there is one directory you have to exclude from tracking, namely node_modules. It is created during either:
-
$ npm install package_name – if there are no dependencies in the
package.json
; -
$ npm install – if there are already defined dependencies in the
package.json
.
The directory contains all libraries specified in the package.json
file and additional modules required by npm itself. Each developer will have this folder downloaded locally by npm, so add it to your .gitignore file:
1 2 3 |
// .gitignore file src/main/resources/static/node_modules/* |
Now you can commit your changes:
1 2 3 4 |
$ git add .gitignore $ git add src/main/resources/static/package.json $ git add src/main/resources/static/package-lock.json $ git commit -m "List of js dependencies added." |
Update or remove a package
A package is identified by its name and version. When you want to change a package version to a newer one (allowed by a ^
or ~
suffix), run
$ npm update package_name . Remember that calling
$ npm update updates all packages in accordance with given ranges.
To remove a package from your project dependencies, execute
$ npm uninstall package_name .
Unify dependencies across all machines
Now every developer working on the project can have the same dependencies installed on his or her local machine by simply running the following command:
1 |
$ npm install |
This will result in installing all required libraries in their given versions. The packages will be placed in the node_modules
directory.
Technically, all libraries can be downloaded manually and placed in the correct directories. However, it is time-consuming and can lead to confusion among the project contributors and errors during collaboration. I think that keeping your node_modules organized with npm makes sharing the project much more effortless.
Automatic security check
From npm@6, you can check the libraries installed in your project for security issues. Just run:
1 |
$ npm audit |
in a directory with the package-lock.json
file and examine the outcome. Some of the found vulnerabilities can be fixed automatically by running:
1 |
$ npm audit fix |
It’s a very convenient way of assuring that your project is free from javascript security liabilities.
You can find countless useful features of npm by browsing its blog. |