Since this blog existed and for many centuries before that, we had - “package managers”. These utilities have been quenching the thirst to build better applications and even better applications while standing on the shoulders of giants that grow ever bigger. Yes, they do all that despite their drab name.
Package managers address a single function - package code and manage dependencies so that they could be used as a whole.
Say, you put together some Javascript code to import file to a database. Theoretically, you could do this right from -
- Interact with operating system to use disk functions
- Go to the directory and read the file
- Recognize contents
- Connect to database using the drivers that is installed in the system
- Stream file content and commit to database
- Disconnect from the world and be at peace
Or, you could just use packages. Packages enable you to sustain code that does a function. You can have a function that reads files, establish DB connection and commit content to database. Now you need to tie up all those packages and write an abstract function that can take a task from point A to point B in a seamless fashion.
Package managers can and typically do much more than that. They make packages that you created available to the world so that everyone else does not need to build in the same packages.
Almost every respected language and operating system have their package managers lined up so that people work together to create magic. Javascript takes it to a whole new level.
Package Managers in Javascript
Javascript packages became popular with Node, but provide different meaning to the term ‘package’. For one Javascript provides some seriously easy way to work with third party packages. You can download code and use them in your modules, or directly reference them over web. And, there is Node.
While Node functions well using abstractions built in lower-level languages to provide execution engine for Javascript on your operating system, it also explodes the inclusivity and usefulness of the packages.
You see Node thrives on packages.
You can use tens or hundreds of thousands of packages on your system to achieve a level of productivity that C developers never dreamed of.
- Create something called ‘package.json’ to list packages used by your app
- Run one command, get everything setup
- Begin working your magic with a head-start provided by the packages
“Node Package Manager” (or NPM) is the package manager that is the most talked about. Created to manage package dependencies right and inspired by package management in PHP/Perl, NPM has given a new meaning to package management.
NPM
NPM gets included along with NodeJS installation. NPM is multi-faceted -
- NPM is the client that runs in your operating system that can install packages with single command (= what gets installed along with Node)
- NPM registry is the database of all NPM packages (packages that are recognized by NPM)
- NPM Inc. is the company behind NPM
Although typically you would install packages from NPM registry, you could have your own package ecosystem if you do so prefer.
Typically we use the public registry and start installing packages through a humble command.
npm i nodemon
This will download the package from [https://www.npmjs.com/package/nodemon] and install it within <current_ folder>\node_modules
NPM is the most popular system and dominates all conversations in Javascript. Anything that is respected in the Javascript world today is not only available in GitHub (the new name for ‘version control system’), but also as a package in NPM for easy install.
NPM maintains version control in the registry. The client downloads packages for the version specified in your main package.json. The magic formula is that the packages chosen by you may also have their own packages through their own package.json. Those packages get downloaded too so that you do not have to go through that pain all by yourself. The cascading package results in those hundreds or thousands of folders that you find in node_modules
directory in a Javascript project.
Further, you can download packages local to the project (i.e., refer to local package.json). Or, install package globally to the machine (e.g. in C:\Users\<windows-user>\AppData\Roaming\npm\
) using the -g
flag.
|
|
When it is time, you can choose to run commands through npm run
, which runs the given command with specified params. It does not run it any faster but certainly makes it consistent across developers.
The typical Javascript flow goes like this..
- Create a package.json file.
- Run
npm i
to install packages local to the project - typically in thenode_modules
folder within your project folder. This pulls up packages from npm registry - Add even more packages by using
npm i awesome-package
- Panic that your
node_modules
is now 3 GB and don’t do anything about it - Write your code in the interim
- Build package using
npm run
, which is just running a utility you chose to provide in the package.json - Use
npm build
to build your app using a utility that you specified in package.json - Rejoice about the completed app. Package that app as NPM package and do great evil
Well, all beautiful there.
But, NPM is no panacea.
- NPM is a registry controlled by a single company and relies on that company to hold up 250K+ packages with more being added by the day
- NPM does not control what goes in. You can create npm package in the next 3 minutes and upload to NPM. No one is going to be bothered much
And, some minor annoyances like -
- Duplicating NPM packages all over the place for individual projects. We could add 1 TB NVMe SSD one day, and looking worn out the next after installing a couple of Meteor projects (and a few games)
- Painfully slow to resolve dependencies and download required components
NPM has a cousin in NPX. A lot of modern package management comes down to not only packaging stuff, but also setting up everything and make them ready to execute. Complex applications today ship their own CLI to achieve this objective (think create-react-app, Vue CLI et al.). NPX tries to solve this problem by accepting a CLI and running it directly rather than downloading CLI yourself and running it. Think of it as syntactic sugar (for now).
There are other package managers today in the Javascript world but they more or less toe the line of NPM since it is so popular!
Yarn
Yarn works out of the same npm package.json and registry, but it is faster. Learn a few more commands and you see yarn zipping around at the expense of more space on your drive.
PNPM
PNPM is young but promising. It is quite fast and promises to install a package once on the disk - so much much cleaner than its competition.
Entropic
Entropic was announced in JSConf. It is federated - as in the idea is to have many computers host packages instead of one. I believe Entropic has the right model to overcome NPM’s centralized repository limitations, but is a long way from being useful to mortal developers (as I understand it, and I often understand things wrong).
Which package manager should I use today?
- Yarn - if you love your life
- PNPM - if you love living on the edge
- NPM - if you like NPX and want to run CLIs remotely
I often jump between NPM and Yarn for individual projects. In fact you can go back and forth - but be careful of messing up your repository.